/**
 * Created by Loriling on 2015/2/25.
 *
 */
define(["js/lib/async" + $E.jsv, 
        "js/workorder/nextstepinfo", 
        "js/workorder/struct", 
        "js/workorder/buttonstatus", 
        "js/objective" + $E.jsv], function(async, NextStepInfo, Struct, ButtonStatus, Objective) {
		
		var ADDIN_WORKORDER = "AddinWOrder";
	    var ADDIN_WORKORDER_USER = "AddinWOrderUser";
	
        var Property_WOSaveStatus = "Temp.WorkOrderSaveStatus";             //动态页面只读，更改无效
        var Property_WOSendStatus = "Temp.WorkOrderSendStatus";			 //动态页面只读，更改无效
        var Property_WOCloseOrReOpenStatus = "Temp.WOCloseReOpenStatus";	 //动态页面只读，更改无效
        var Property_WOEndStatus = "Temp.WOEndStatus";
        var Property_WOReOpenStatus = "Temp.WOReOpenStatus";
        var Property_WOCancelStatus = "Temp.WorkOrderCancelStatus";		 //动态页面只读，更改无效
        var Property_WOFailedStatus = "Temp.WorkOrderFailedStatus";		 //动态页面只读，更改无效
        var Property_WOTakeOverStatus = "Temp.WorkOrderTakeOverStatus";	 //动态页面只读，更改无效
        var Property_WOCDStatus = "Temp.WorkOrderCDStatus";				 //动态页面只读，更改无效
        var Property_WOBackStatus = "Temp.WorkOrderBackStatus";			 //动态页面只读，更改无效
        var Property_WOReplyCustomerStatus = "Temp.WorkOrderReplyStatus";	 //动态页面只读，更改无效
        var Property_WoCloseFlag = "Temp.WorkOrderCloseFlag";	 			 //动态页面只读，更改无效
        var Property_WoCurrentHandleGrP="Temp.WoCurrentGrp";				 //当前处理组
        var Property_WoCurrentHandleBy="Temp.WoCurrentBy";					 //当前处理人

        var Property_WONextStepID = "Temp.WONextStepID"; 					//指定下一步步骤
        var Property_WONextStepIDMap = "Temp.WONextStepIDMap"; 				//指定下一步步骤MAPid
        var Property_WOSendNextStepGroupID = "Temp.WoSendNextGroupID"; 	 	//强制下送给XXX组
        var Property_WOSendNextStepStaffID = "Temp.WoSendNextStaffID"; 	 	//强制下送给XXX组中的XXX人,必须选配组
        var Property_WOSendNextStepBeginDate = "Temp.WOSendStepBeginDate";	//下送步骤开始时间
        var Property_WOSendNextEndDate = "Temp.WOSendStepExpireDate";		//下送步骤过期时间
        var Property_WOBackGrpID="Temp.WoBackGroupID";						//强制退回给组
        var Property_WOBackStaffID="Temp.WoBackStaffID";					 	//强制退回给人 (必须要设组，人才有效)
        var Property_WorkOrderStepComments = "Temp.WOStepComments" ;			//步骤上的Comments
        var Property_WorkOrderStepID="Temp.WOStepID";
        var Property_WorkOrderStepStatus="Temp.WOStepStatus";
        var Property_WorkOrderSubStepID="Temp.CurSubStepID";   				//当前协办步骤ID
        var Property_WorkOrderRunSubStepID="Temp.CurRunSubStepID";   		//当前协办步骤ID WorkOrder_SUB2
        var Property_WorkOrderTabClose="Temp.WOTabClose";					//关闭TAB页

        var Property_WOSendNextSubStepInfo="Temp.WOSubStepInfo";				//协办步骤处理信息
        //格式: 步骤ID，0/1(1表示这个协办步骤忽略),处理组，处理人|步骤ID，0/1(1表示这个协办步骤忽略),处理组，处理人|步骤ID，0/1(1表示这个协办步骤忽略),处理组，处理人.....

        var Property_ShowWorkOrderHistory = "Temp.ShowWorkOrderHistory";
        var Property_ShowWorkOrderCDHistory  = "Temp.ShowCDHistory";
        var Property_WorkOrderFrameID  = "Temp.WorkOrderFrameID";
        var Property_WorkOrderWorkOrderPriority = "Temp.WorkOrderPriority";
        var Property_WorkOrderWorkOrderExpireDate = "Temp.WorkOrderExpireDate";
        var Property_WorkOrderForeCastDate = "Temp.WOForecastDate";
        var Property_WorkOrderStepForeCastDate = "Temp.WOStepForecastDate";
        var Property_WorkOrderStatus="Temp.WorkOrderStatus";
        var Property_WorkOrderNewFlag = "Temp.WorkOrderNewFlag";

        var Property_OWorkOrderSave  = "Temp.WorkOrderSave";
        var Property_OWorkOrderSend  = "Temp.WorkOrderSend";
        var Property_OWorkOrderCloseOrReOpen  = "Temp.WOCloseReOpen";
        var Property_OWorkOrderEnd  = "Temp.WOEnd";
        var Property_OWorkOrderReOpen  = "Temp.WOReOpen";
        var Property_OWorkOrderCancel  = "Temp.WorkOrderCancel";
        var Property_OWorkOrderFailed  = "Temp.WorkOrderFailed";
        var Property_OWorkOrderTakeOver  = "Temp.WorkOrderTakeOver";
        var Property_OWorkOrderCD  = "Temp.WorkOrderCD";
        var Property_OWorkOrderBack  = "Temp.WorkOrderBack";
        var Property_OWorkOrderReplyCustomer  = "Temp.WorkOrderReply";

        var structs = {};


        /**
         * 从缓存中获取工单主结构，如果缓存中没有则去服务端加载
         * @method fetchStruct
         * @param project
         * @param workorderId
         * @returns {*}
         */
        var fetchStruct = function(project, workorderId){
            var struct = structs[project.id + '_' + workorderId];
            if (struct == undefined) {
                struct = loadStruct(project, workorderId);
                structs[project.id + '_' + workorderId] = struct;
            }
            return struct;
        };

        /**
         * 从服务器加载工单的主结构数据
         * @method loadStruct
         * @param project {object} 项目对象
         * @param workorderId {string} 动态页面FAKE ID
         * @return {object} 动态页面结构主数据
         */
        var loadStruct = function(project, workorderId) {
            var struct;
            $F.logGroup("WorkOrder - loadStruct", "Load workorder structure, project.id: " + project.id + " ID: " + workorderId);
            $F.dataService('SysCacheJSON', {
                async : false,
                data : {
                    Key : project.token,
                    DBKey : '',
                    Name : 'WO.Client.Get',
                    O : 'M',
                    MainID : workorderId,
                    SubID : '',
                    lang: $E.language
                },
                digest : project.digest,
                success : function(data) {
                    if (data.code > 0) {
                        console.log(data.value);
                        struct = new Struct(data.value);
                    } else{
                        $F.alert('工单主数据加载失败：<br/>' + data.message);
                    }
                },
                fail : function(xhr){
                    $F.alert("ajax error: "+xhr.responseText);
                }
            });
            $F.logGroupEnd();
            return struct;
        };

        var Workorder = function(project){
            var wo = this;
            var WOEXPF = project.getParam("WOEXPF") || "StringField1,StringField2,StringField3,StringField4,StringField5";

            this.guid = "";
            this.frameId = "";
            this.oldFrameId = "";
            this.oldStepId = "";
            this.struct = {};
            this.showBuildId;
            this.instance;
            this.newFlag = 0;

            var bd = new BoundData("Workorder2" + $E.staff.epidSql);
            bd.KeyInfoEdit("workorder_guid");
            bd.setCreateInfo("CREATEDDATE", "CREATEDBY", $E.staff.id);
            bd.setModifyInfo("MODIFIEDDATE", "MODIFIEDBY", $E.staff.id);
            this.woBoundData = bd;

            this.buttonStatus = new ButtonStatus(project);
            this.nextStepInfo = new NextStepInfo(project, wo);

            this.currentSubStepID = "";
            this.currentSubStepRunID = "";

            //from OneWorkOrder
            var _TmpStr1;
            var _TmpStr2;
            var _TmpStr3;
            var _TmpStr4;
            var _TmpStr5;
            var _TmpStr6;
            var _TmpStr7;
            var _TmpStr8;
            var _TmpStr10;
            var _TmpStr11;
            var _TmpStr12;

            this.curStepId;

            this.allExtFields = {};
            this.stepFieldInfo = {};

            this.cacheAllExtField = function(extFields){
                extFields = extFields.trim();
                if ($F.isEmpty(extFields)){
                    return;
                }
                var extFieldsArray = extFields.split(",");
                extFieldsArray.forEach(function(extField){
                    if(!$F.isEmpty(extField)){
                        wo.allExtFields[extField.trim().toUpperCase()] = extField;
                        $F.log("OneWorkOrder.CacheAllExtField", "Exp Fileds:" + extField);
                    }
                });
            };

            this.getPriorityId = function(){
                return wo.woBoundData.getValue("Priority_ID");
            };
            this.setPriorityId = function(vValue){
                wo.woBoundData.NewValueEdit("Priority_ID", vValue);
            };
            this.getExpiredDate = function(){
                return wo.woBoundData.getValue("ExpiredDate");
            };
            this.setExpiredDate = function(vValue){
                wo.woBoundData.NewValueEdit("ExpiredDate", vValue);
            };
            this.getForecastDate = function(){
                return wo.woBoundData.getValue("ForecastDate");
            };
            this.setForecastDate = function(vValue){
                wo.woBoundData.NewValueEdit("ForecastDate", vValue, $CONST.BoundType.F_Date);
            };
            this.getStepForecastDate = function() {
                return wo.woBoundData.getValue("StepForecastDate");
            };
            this.setStepForecastDate = function(vValue){
                wo.woBoundData.NewValueEdit("StepForecastDate", vValue, $CONST.BoundType.F_Date);
            };

            this.setCurStepId = function(stepId){
                wo.woBoundData.NewValueEdit("curstep_id", stepId);
            };
            this.getCurStepId = function(){
                return wo.woBoundData.getValue("curstep_id");
            };
            this.setExpectStartTime = function(expectStartTime){
                wo.woBoundData.NewValueEdit("expectstarttime", expectStartTime, $CONST.BoundType.F_Date);
            };
            this.getExpectStartTime = function(){
                return wo.woBoundData.getValue("expectstarttime");
            };
            this.setHandleGroupId = function(grpId){
                wo.woBoundData.NewValueEdit("handlegroup_id", grpId);
            };
            this.getHandleGroupId = function(){
                return wo.woBoundData.getValue("handlegroup_id");
            };
            this.setHandleById = function(handleById){
                wo.woBoundData.NewValueEdit("handleby_id", handleById);
            };
            this.getHandleById = function(){
                return wo.woBoundData.getValue("handleby_id");
            };
            this.setExpiredHandleGroupId = function(expGrpId){
                wo.woBoundData.NewValueEdit("expiredhandlegroup_id", expGrpId);
            };
            this.getExpiredHandleGroupId = function(){
                return wo.woBoundData.getValue("expiredhandlegroup_id");
            };
            this.setExpiredHandleById = function(expHandleById){
                wo.woBoundData.NewValueEdit("expiredhandleby_id", expHandleById);
            };
            this.getExpiredHandleById = function(){
                return wo.woBoundData.getValue("expiredhandleby_id");
            };
            this.setStepExpiredDate = function(stepExpiredDate){
                wo.woBoundData.NewValueEdit("stepexpireddate", stepExpiredDate, $CONST.BoundType.F_Date);
            };
            this.getStepExpiredDate = function(){
                return wo.woBoundData.getValue("stepexpireddate");
            };
            this.setCurStepIdMap = function(curStepIdMap){
                wo.woBoundData.NewValueEdit("curstep_id_map", curStepIdMap)
            };
            this.getCurStepIdMap = function(){
                return wo.woBoundData.getValue("curstep_id_map");
            };
            this.setCurStepComments = function(curStepComments){
                wo.woBoundData.NewValueEdit("curstepcomments", curStepComments);
            };
            this.getCurStepComments = function(){
                return wo.woBoundData.getValue("curstepcomments");
            };
            this.setCurStepStatus = function(curStepStatus){
                wo.woBoundData.NewValueEdit("curstepstatus", curStepStatus);
            };
            this.getCurStepStatus = function(){
                return wo.woBoundData.getValue("curstepstatus");
            };
            this.setWorkOrderStatus = function(workOrderStatus){
                wo.woBoundData.NewValueEdit("WorkOrderStatus",workOrderStatus);
            };
            this.getWorkOrderStatus = function(){
                return wo.woBoundData.getValue("WorkOrderStatus");
            };


            var searchObjective = function(objectiveGuid){
                var objective;
                var sqlKey = "ECore.Objective.selectByGuid";
                var data = project.commonQuerySync(sqlKey, [$E.staff.epidSql, objectiveGuid]);
                if(data && data.value[0].count > 0){
                    objective = {
                        objectivetype_id : data.value[0].fields[0][0],
                        customer_guid : data.value[0].fields[0][1]
                    };
                }else{//查找工单MENU信息失败
                    $F.log("workorder", "No objective found by objective_guid: " + objectiveGuid);
                }
                return objective;
            };

            var searchWorkorder = function(workorderGuid){
                var workorder;
                var sqlKey = "ECore.Workorder.selectInfo";
                var data = project.commonQuerySync(sqlKey, [$E.staff.epidSql, workorderGuid]);
                if(data && data.value[0].count > 0){
                    workorder = {
                        frame_id : data.value[0].fields[0][0],
                        customer_guid : data.value[0].fields[0][1]
                    };
                }else{
                    $F.warn("workorder", "No Workorder found by workorder_guid: " + workorderGuid);
                }
                return workorder;
            };

            //1.load by objective_guid [from WorkOrderLib.as line 321]
            //根据oId打开工单
            this.loadByObjectiveGuid = function(objectiveGuid, addinId, tabName, parameters){
            	$F.log('Workorder - loadByObjectiveGuid', '打开工单，ObjectiveGuid: ' + objectiveGuid);
                var workorderBasicInfo;
                var objective = loadObjectiveByGuid(objectiveGuid, "");
                if($F.isEmpty(objective)){
                    workorderBasicInfo = searchWorkorder(objectiveGuid);
                    if($F.isEmpty(workorderBasicInfo)){
                        $F.err("Workorder - loadByObjectiveGuid", "No workorder found by workorder_guid: " + objectiveGuid);
                        return -1;
                    }
                    workorderBasicInfo.objectivetype_id = objective.getValue("OBJECTIVETYPE_ID");
                }else{
                    var objectiveTypeId = objective.getValue("OBJECTIVETYPE_ID");
                    var customerGuid = objective.getValue("customer_guid");
                    var objectiveTypeObj = project.getObjectiveType(objectiveTypeId);
                    var addinCmtId = "";
                    if(objectiveTypeObj){
                        addinCmtId = objectiveTypeObj.addinCmtId;
                    }else{
                        $F.log("Workorder - loadByObjectiveGuid", "no workorder found with objectiveTypeId: "+objectiveTypeId);
                        return -1;
                    }
                    workorderBasicInfo = {
                        frame_id : addinCmtId,
                        customer_guid : customerGuid,
                        objectivetype_id : objectiveTypeId
                    };
                }
                wo.customer_guid = workorderBasicInfo.customer_guid;
                wo.struct = fetchStruct(project, workorderBasicInfo.frame_id);
                if ($F.isEmpty(wo.struct)){
                    $F.err("WorkOrder.loadByObjectiveGuid", "Not found workorder config by objective_guid: " + objectiveGuid);
                    return -1;
                }
                return loadWorkorder(objectiveGuid, objective, 0, addinId, tabName, parameters);
            };


            //2.load by objectivetype_id
            //根据otId打开工单，可能是新建工单
            this.loadByOtId = function(otId, dupFlag, addinId, tabName, parameters){
                var objectiveTypeObj = project.getObjectiveType(otId);
                var addinCmtId = "";
                if(objectiveTypeObj){
                    addinCmtId = objectiveTypeObj.addinCmtId;
                }else{
                    $F.alert("no workorder found with objectiveTypeId: " + otId);
                    return -1;
                }
                wo.frameId = addinCmtId;
                wo.struct = fetchStruct(project, addinCmtId);
                if ($F.isEmpty(wo.struct)){
                    $F.alert("没有找到工单配置:"+ objectiveGuid,"WorkOrder.WOClientByOBJGuid");
                    return -1;
                }

                var allStruct = wo.struct.getStruct();
                var mCustomer_GUID = allStruct.CustGuid;
                var mCustomerFlag = allStruct.CustFlag;
                $F.log("WorkOrder.WOClientShowIn", "Wo change Customer:" + mCustomer_GUID + " Flag:" + mCustomerFlag);

                var mUserCustomer_GUID;
                var currentCustomerGuid = project.getCustomerGuid();
                if (!$F.isEmpty(mCustomer_GUID)){
                    while(mCustomer_GUID.length < 36){
                        mCustomer_GUID = mCustomer_GUID + " ";
                    }
                	if (mCustomerFlag == 0){
                		if($F.isEmpty(currentCustomerGuid)){
                            $F.alert('当前系统中无客户对象，请先选择客户');
                            return -1;
                        }
                		mUserCustomer_GUID = currentCustomerGuid;                		
                	}else if (mCustomerFlag == 1){
                        mUserCustomer_GUID = mCustomer_GUID;
                        $F.log("WorkOrderLab.WOClientShowIn", "Use workorder default customer : " + mCustomer_GUID);
                    }else{
                        if($F.isEmpty(currentCustomerGuid)){
                            mUserCustomer_GUID = mCustomer_GUID;
                            $F.log("WorkOrderLab.WOClientShowIn", "Current customer is null, use workorder default customer : "+mCustomer_GUID);
                        }else{
                            mUserCustomer_GUID = currentCustomerGuid;
                        }
                    }
                }else{
                    if($F.isEmpty(currentCustomerGuid)){
                        $F.alert('当前系统中无客户对象，请先选择客户');
                        return -1;
                    }
                    mUserCustomer_GUID = currentCustomerGuid;
                }
                $F.log("WorkOrderLib.WOClientShowIn", "Current Customer GUID : " + mUserCustomer_GUID);
                wo.customer_guid = mUserCustomer_GUID;

                var objective = loadOneObjective(otId, mUserCustomer_GUID, dupFlag);
                var workorderGuid = objective.boundData.getValue("objective_guid");
                return loadWorkorder(workorderGuid, objective, 0, addinId, tabName, parameters);
            };


            //3.load by sub step id
            this.loadBySubStep = function(subId, addinId, tabName, parameters){
                // ("select WorkOrder_GUID,SubStatus,HandleGroup_ID,HandleBy_ID,child_id,workordernode_id from WorkOrder2_Sub"+cRootClass.getInstance().getEPIDExtTB()+" where Sub_GUID='"+ vSubWo+"'");
                var ret = project.commonQuerySync("ECore.workorder.WOSub1", [$E.staff.epidSql, subId]);
                if($F.isNull(ret)){
                    $F.alert("协办工单表结构不存在");
                    $F.log("WorkOrder.WOClientBySubStepGuid", "No workorder sub table found.");
                    return -1;
                }else if(ret.value[0].count == 0){
                    $F.alert("协办工单不存在");
                    $F.log("WorkOrder.WOClientBySubStepGuid", "No workorder sub found.");
                    return -1;
                }

                var handleGroupId =  $F.trimToEmpty(ret.value[0].fields[0][2]);
                if(handleGroupId == project.groupId){
                    var handleById = $F.trimToEmpty(ret.value[0].fields[0][3]);
                    if(handleById == "" || handleById == $E.staff.id){
                        var childId = ret.value[0].fields[0][4];
                        var nodeId = ret.value[0].fields[0][5];
                        var objectiveGuid = ret.value[0].fields[0][0];
                        var objective = loadObjectiveByGuid(objectiveGuid, "");
                        var mWorkOrderIDA,mCustomerGUID;
                        if($F.isNull(objective)){
                            //select workorderframe_id,customer_GUID from workorder2{C1} where workorder_guid=@{C2}S
                            var data = project.commonQuerySync("ECore.Workorder.WOInfo", [$E.staff.epidSql, objectiveGuid]);
                            if($F.isNull(data) || data.value[0].count == 0){
                                $F.alert("工单Objective加载失败,没有找到对应的workorder2");
                                this.clearInfo();
                                return -1;
                            }else{
                                mWorkOrderIDA = data.value[0].fields[0][0];
                                mCustomerGUID = data.value[0].fields[0][1];
                            }
                        }else{
                            var objectiveTypeId = objective.getValue("OBJECTIVETYPE_ID");
                            var objectiveTypeObj = project.getObjectiveType(objectiveTypeId);

                            var addinCmtId = "";
                            if(objectiveTypeObj){
                                addinCmtId = objectiveTypeObj.addinCmtId;
                            }else{
                                $F.alert("查找工单MENU信息失败: " + objectiveTypeId);
                                $F.log("Workorder.loadBySubStep", "no workorder found with objectiveTypeId: "+objectiveTypeId);
                                return -1;
                            }
                            if ($F.isNull(objectiveTypeObj)){
                                this.clearInfo();
                                return -1;
                            }
                            mWorkOrderIDA = addinCmtId;
                            mCustomerGUID = objective.getValue("CUSTOMER_GUID");

                            wo.struct = fetchStruct(project, mWorkOrderIDA);
                            if ($F.isNull(wo.struct)){
                                $F.alert("没有找到工单配置:" + objectiveGuid);
                                $F.log("WorkOrder.loadByObjectiveGuid", "Not found workorder config by objective_guid: " + objectiveGuid);
                                return -1;
                            }

                            var oneNode = struct.getOneNode(nodeId);
                            if($F.isNull(oneNode)){
                                $F.log("WorkOrder.WOClientBySubStepGuid", "Not found workorder node: " + nodeId);
                                $F.alert("没有找到工单配置步骤:" + nodeId);
                                this.clearInfo();
                                return -1;
                            }
                            var oneStep = struct.getOneSub(childId);
                            if($F.isNull(oneStep)){
                                $F.log("WorkOrder.WOClientBySubStepGuid", "Not found workorder sub step: " + childId);
                                $F.alert("没有找到工单配置子步骤:" + childId);
                                this.clearInfo();
                                return -1;
                            }

                            
                            //Sub Step 1可以处理（退）， 2 1可以处理（不可退） 3 只显示
                            var subFlag = 3;
                            if(oneStep.CanBack == 1 && oneStep.OnlyShow == 1){
                            	subFlag = 1;
                            }else if(oneStep.OnlyShow == 1){
                            	subFlag = 2;
                            }
                            loadWorkorder(objectiveGuid, null, subFlag, addinId, tabName, subId, parameters);
                        }
                    }
                }
                return -1;
            };


            var loadOneObjective = function(otId, customerGuid, dupFlag){
                var defaultCustomerGuid = project.getParam("CustDF");
                var objective;
                if($F.equalsIgnoreCase(customerGuid, defaultCustomerGuid)){
                    objective = createNewObjective(otId, customerGuid);
                }else{
                    if(dupFlag > 0){
                        objective = createNewObjective(otId, customerGuid, "");
                    }else{
                        objective = loadObjective(otId, customerGuid, "");
                    }
                }
                return objective;
            };
            var createNewObjective = function(otId, customerGuid, extTBName){
                var objective = Objective.create(project, extTBName);
                objective.createData(otId, Guid.raw());
                objective.modifyOneObjectiveValue("CUSTOMER_GUID", customerGuid);
                objective.boundData.setCreateInfo("CREATEDDATE", "CREATEDBY", $E.staff.id);
                objective.boundData.setModifyInfo("MODIFIEDDATE", "MODIFIEDBY", $E.staff.id);
                return objective;
            };
            var loadObjective = function(otId, customerGuid, extTBName){
                var objective = createNewObjective(otId, customerGuid, extTBName);
                var ret = project.commonQuerySync("ECore.Objective.selectDetailByTypeIdAndCustomer", [$E.staff.epidSql, otId, customerGuid]);
//            {"code":1,"value":[{"columns":["OBJECTIVE_GUID","OBJECTIVETYPE_ID","HANDLEBY_ID","HANDLEGROUP_ID","PRIORITY_ID","EXPIREDDATE","CUSTOMER_GUID","SUBSCRIBER_GUID","ACCOUNT_GUID","FIRSTCONTACTDATE","LASTCONTACTDATE","OBJECTIVESTATUS","ISCONTACT","TRYTIMES","SUCCESSFULCONTACTTIMES","USERDEFINEDSTATUS","COMMENTS","STRINGFIELD1","STRINGFIELD2","CREATEDBY","CREATEDDATE","MODIFIEDBY","MODIFIEDDATE","CALLRESULT_ID","CALLRESULTREASON_ID","PREOBJECTIVE_GUID","EVENT_GUID","EXPECTTRADEDATE","FAILREASON","QUANTITY","AMOUNT","OBDNIS","OBSTATUS","OBSTARTTIME","OBENDTIME","OBHANDLEGROUP","OBHANDLEBY","CUSTLISTNAME","CONTACTPHONE","OBJECTIVETRYSTATUS","LAST1EVENT_GUID","LAST2EVENT_GUID","LAST3EVENT_GUID","LAST4EVENT_GUID","LAST5EVENT_GUID","DEALGROUP_ID","DATATYPE","FIRSTCALLDATE","FAILURE_ATTEMPT","CONTACT_CUSTOMER_GUID","PASSFLAG","CUSTOMERLEVEL","LOCALTRYCOUNT","LASTASSIGNDATE","FAILSTATUS","SUCCESSSTATUS","TEMPLABLE","ISANSWER","ORDERSTATUS"],
//              "key":"ECore.Objective.selectDetailByTypeIdAndCustomer" ,"fields" :[],"count" :0,"pages" :1}]}
                if(!$F.isNull(ret) && ret.value[0].count > 0){
                    for(var i=0;i<ret.value[0].columns.length;i++){
                        var f = ret.value[0].columns[i];
                        if(!$F.equalsIgnoreCase(f, "CREATEDBY") && !$F.equalsIgnoreCase(f, "MODIFIEDBY")){
                            var v = ret.value[0].fields[0][i];
                            objective.setValue(f, v);
                        }
                    }
                    objective.flag = 0;
                }
                return objective;
            };
            var loadObjectiveByGuid = function(oId, extTBName){
                var ret = project.commonQuerySync("ECore.Objective.selectDetailByGuid", [$E.staff.epidSql, oId]);
                if(!$F.isNull(ret) && ret.value[0].count > 0){
                    var otId = ret.value[0].fields[0][1];
                    var customerGuid = ret.value[0].fields[0][6];
                    var objective = createNewObjective(otId, customerGuid, extTBName);
                    if(!$F.isNull(ret) && ret.value[0].count > 0){
                        for(var i=0;i<ret.value[0].columns.length;i++){
                            var f = ret.value[0].columns[i];
                            if(!$F.equalsIgnoreCase(f, "CREATEDBY") && !$F.equalsIgnoreCase(f, "MODIFIEDBY")){
                                var v = ret.value[0].fields[0][i];
                                objective.setValue(f, v);
                            }
                        }
                        objective.flag = 0;
                    }
                    return objective;
                }else{
                    return null;
                }
            };

            var loadMeData = function(workorderGuid){
                wo.cacheAllExtField(WOEXPF);
                var expFields = WOEXPF;
                if(!expFields.startWith(",")){
                    expFields = ","+expFields
                }
                wo.woBoundData.NewValueEdit("WorkOrder_GUID", workorderGuid);
                wo.guid = workorderGuid;
                var data = project.commonQuerySync("ECore.Workorder.selectWODetailInfo", [expFields, $E.staff.epidSql, workorderGuid]);
                if($F.isEmpty(data)){
                    return -1;
                }
//            Select WorkOrder_GUID,WorkOrderFrame_ID,Category,Priority_ID,ExpiredDate,Customer_GUID,WorkOrderStatus,CurStep_ID,ExpectStartTime,StepExpiredDate,CurStepStatus,HandleGroup_ID,HandleBy_ID,
//                ProcessFlag,CurStepComments,ExpiredHandleBy_ID,ExpiredHandleGroup_ID,ForecastDate,StepForecastDate,CurStep_ID_MAP{C1}
//            From WorkOrder2{C2} Where WorkOrder_GUID=@{C3}S
                if(data.value[0].count > 0){
                    wo.woBoundData.OldValue("WorkOrderFrame_ID", data.value[0].fields[0][1]);
                    wo.woBoundData.OldValue("Category",data.value[0].fields[0][2]);
                    wo.woBoundData.OldValue("Priority_ID",data.value[0].fields[0][3]);
                    wo.woBoundData.OldValue("ExpiredDate",data.value[0].fields[0][4],$CONST.BoundType.F_Date);
                    wo.woBoundData.OldValue("Customer_GUID",data.value[0].fields[0][5]);
                    wo.woBoundData.OldValue("WorkOrderStatus",data.value[0].fields[0][6]);
                    wo.woBoundData.OldValue("CurStep_ID",data.value[0].fields[0][7]);
                    wo.woBoundData.OldValue("ExpectStartTime",data.value[0].fields[0][8],$CONST.BoundType.F_Date);
                    wo.woBoundData.OldValue("StepExpiredDate",data.value[0].fields[0][9],$CONST.BoundType.F_Date);
                    wo.woBoundData.OldValue("CurStepStatus",data.value[0].fields[0][10]);
                    wo.woBoundData.OldValue("HandleGroup_ID",data.value[0].fields[0][11]);
                    wo.woBoundData.OldValue("HandleBy_ID",data.value[0].fields[0][12]);
                    wo.woBoundData.OldValue("ProcessFlag",data.value[0].fields[0][13],$CONST.BoundType.F_Int);
                    wo.woBoundData.OldValue("CurStepComments",data.value[0].fields[0][14]);
                    wo.woBoundData.OldValue("ExpiredHandleBy_ID",data.value[0].fields[0][15]);
                    wo.woBoundData.OldValue("ExpiredHandleGroup_ID",data.value[0].fields[0][16]);
                    wo.woBoundData.OldValue("ForecastDate",data.value[0].fields[0][17],$CONST.BoundType.F_Date);
                    wo.woBoundData.OldValue("StepForecastDate",data.value[0].fields[0][18],$CONST.BoundType.F_Date);
                    wo.woBoundData.OldValue("CurStep_ID_MAP",data.value[0].fields[0][19]);

                    wo.setCurStepComments(data.value[0].fields[0][14]);
                    wo.setCurStepIdMap(data.value[0].fields[0][19]);
                    //LoadExpField
                    for(var i= 0,expfarr = WOEXPF.split(",");i<expfarr.length;i++){
                        var expf = expfarr[i];
                        wo.woBoundData.OldValue(expf, data.value[0].fields[0][20+i]);
                    }
                    return 0;
                }else{
                    var allStruct = wo.struct.getStruct();
                    var mStepID = wo.struct.getFirstNode();// _RunData.CurStep_ID;
                    var mOneStep = wo.struct.getOneNode(mStepID);
                    var mStepPeriodType,mStepPeriodLen,mStepForeUnit,mStepForeLen,mExpGrp,mExpBy;
                    if (!$F.isNull(mOneStep)){
                        mStepPeriodType = mOneStep.ExpiredPeriodTypeId;
                        mStepPeriodLen = mOneStep.ExpiredPeriod;
                        mStepForeUnit = mOneStep.ForecastUnit;
                        mStepForeLen = mOneStep.ForecastLen;
                        mExpGrp = mOneStep.ExpiredGrpId;
                        mExpBy = mOneStep.ExpiredById
                    }
                    var curStepIdMap = "";
                    if(wo.addinId === ADDIN_WORKORDER_USER){
                        //新建工单时候，如果是用户工单，需要获取到启动的twonodemapid
                        //select NODEMAP_GUID from two_node_map{C1} where beginflag = 1 and frame_id = @{C2}S and WORKORDERNODE_ID_ORIGINAL = @{C3}S
                        var data = project.commonQuerySync("ECore.Workorder.queryTwoNodeMap", [$E.staff.epidSql, wo.frameId, mStepID]);
                        if(data && data.value[0].count > 0){
                            curStepIdMap = data.value[0].fields[0][0];
                        }
                    }
                    wo.newMeData(wo.frameId, wo.struct.getFirstNode(), wo.customer_guid, workorderGuid, allStruct.PriorityId, allStruct.Category,
                        allStruct.ExpiredPeriodTypeId, allStruct.ExpiredPeriod, allStruct.ForecastUnit, allStruct.ForecastLen,
                        mStepPeriodType, mStepPeriodLen, mStepForeUnit, mStepForeLen, mExpGrp, mExpBy, curStepIdMap);
                    return 1;
                }
            };

            this.newMeData = function(vFrame_ID, vFirstNode,vCustomer_GUID,vWorkorderGUID,
                                      vPriority,vCATEGORY,vExpiredPeriodType_ID,vExpiredPeriod,vForecastUnit,vForecastLen,
                                      vStepExpiredPeriodType_ID,vStepExpiredPeriod,vStepForecastUnit,vStepForecastLen,
                                      vExpiredHandleGroup_ID,vExpiredHandleBy_ID,vCurStep_ID_Map){
                var _WOrderBound = wo.woBoundData;
                _WOrderBound.NewValueEdit("WorkOrder_GUID",vWorkorderGUID);
                _WOrderBound.NewValueEdit("CurStep_ID",vFirstNode);
                _WOrderBound.NewValueEdit("CATEGORY",vCATEGORY);
                _WOrderBound.NewValueEdit("PRIORITY_ID",vPriority);
                _WOrderBound.NewValueEdit("WORKORDERFRAME_ID",$F.trimToEmpty(vFrame_ID));
                _WOrderBound.NewValueEdit("CUSTOMER_GUID",vCustomer_GUID);
                _WOrderBound.NewValueEdit("WorkOrderStatus",$CONST.WO.WO_SysOpen);
                _WOrderBound.NewValueEdit("CurStepStatus",$CONST.WO.WO_SysOpen);
                _WOrderBound.NewValueEdit("HandleGroup_ID",project.groupId);
                _WOrderBound.NewValueEdit("HandleBy_ID",$E.staff.id);
                _WOrderBound.NewValueEdit("ExpiredHandleGroup_ID",vExpiredHandleGroup_ID);
                _WOrderBound.NewValueEdit("ExpiredHandleBy_ID",vExpiredHandleBy_ID);
                var mCurDate = $F.getDbTime();//
                _WOrderBound.NewValueEdit("expectstarttime",mCurDate,$CONST.BoundType.F_Date);
                var mExpiredDate = getNextEndDate(mCurDate,vExpiredPeriodType_ID,vExpiredPeriod);
                _WOrderBound.NewValueEdit("EXPIREDdate",mExpiredDate,$CONST.BoundType.F_Date);
                var mForecastdate = getNextEndDate(mCurDate,vForecastUnit,-vForecastLen);
                _WOrderBound.NewValueEdit("forecastdate",mForecastdate,$CONST.BoundType.F_Date);
                mExpiredDate = getNextEndDate(mCurDate,vStepExpiredPeriodType_ID,vStepExpiredPeriod);
                _WOrderBound.NewValueEdit("StepExpireddate",mExpiredDate,$CONST.BoundType.F_Date);
                mForecastdate = getNextEndDate(mCurDate,vStepForecastUnit,-vStepForecastLen);
                _WOrderBound.NewValueEdit("stepforecastdate",mForecastdate,$CONST.BoundType.F_Date);
                _WOrderBound.NewValueEdit("CurStep_ID_MAP",vCurStep_ID_Map);
                wo.setCurStepComments("");
                wo.setCurStepIdMap("");
            };

            var loadWorkorderData = function(workorderGuid, subFlag){
                //清空instance里的xmldos请求，避免重复记录了之前的xmldos请求
                wo.instance.xmldosRemoveAll();

                var newFlag = loadMeData(workorderGuid);
                wo.newFlag = newFlag;
                var currentStepId = wo.woBoundData.getValue("CurStep_ID");
                if(newFlag == 1){//new wo
                    wo.oldFrameId = "";
                    wo.oldStepId = "";
                }else{
                    wo.oldFrameId = wo.woBoundData.getValue("WORKORDERFRAME_ID");
                    wo.oldStepId = currentStepId;
                }
                wo.frameId = wo.oldFrameId;
                wo.curStepId = currentStepId;
                wo.buttonStatus.setCurrentWOStatus(wo, newFlag, subFlag);

                var fields = {};
                fields[Property_WOSaveStatus] = {type: 0, data: wo.buttonStatus._SaveStatus==1?1:0};
                fields[Property_WOSendStatus] = {type: 0, data: wo.buttonStatus._SendStatus==1?1:0};
                fields[Property_WOCloseOrReOpenStatus] = {type: 0, data: wo.buttonStatus._CloseOrOpenStatus==1?1:0};
                fields[Property_WOEndStatus] = {type: 0, data: wo.buttonStatus._EndStatus==1?1:0};
                fields[Property_WOReOpenStatus] = {type: 0, data: wo.buttonStatus._ReOpenStatus==1?1:0};
                fields[Property_WOCancelStatus] = {type: 0, data: wo.buttonStatus._CancelStatus==1?1:0};
                fields[Property_WOFailedStatus] = {type: 0, data: wo.buttonStatus._FailedStatus==1?1:0};
                fields[Property_WOTakeOverStatus] = {type: 0, data: wo.buttonStatus._TakeOverStatus==1?1:0};
                fields[Property_WOCDStatus] = {type: 0, data: wo.buttonStatus._CDStatus==1?1:0};
                fields[Property_WOBackStatus] = {type: 0, data: wo.buttonStatus._BackStatus==1?1:0};
                fields[Property_WOReplyCustomerStatus] = {type: 0, data: wo.buttonStatus._ReplyCustomerStatus==1?1:0};
                fields[Property_WoCloseFlag] = {type: 0, data: wo.buttonStatus._CloseFlag};
                fields[Property_WorkOrderStepComments] = {type: 0, data: wo.woBoundData.getValue("CurStepComments")};
                fields[Property_WoCurrentHandleBy] = {type: 0, data: wo.woBoundData.getValue("HandleBy_ID")};
                fields[Property_WoCurrentHandleGrP] = {type: 0, data: wo.woBoundData.getValue("HandleGroup_ID")};
                fields[Property_WorkOrderFrameID] = {type: 0, data: wo.woBoundData.getValue("WorkOrderFrame_ID")};
                fields[Property_WorkOrderWorkOrderPriority] = {type: 0, data: wo.woBoundData.getValue("Priority_ID")};
                fields[Property_WorkOrderWorkOrderExpireDate] = {type: 0, data: wo.woBoundData.getValue("ExpiredDate")};
                fields[Property_WorkOrderForeCastDate] = {type: 0, data: wo.woBoundData.getValue("ForecastDate")};
                fields[Property_WorkOrderStepForeCastDate] = {type: 0, data: wo.woBoundData.getValue("StepForecastDate")};
                fields[Property_WorkOrderStatus] = {type: 0, data: wo.woBoundData.getValue("WorkOrderStatus")};
                fields[Property_WorkOrderStepID] = {type: 0, data: wo.woBoundData.getValue("CurStep_ID")};
                fields[Property_WorkOrderStepStatus] = {type: 0, data: wo.woBoundData.getValue("CurStepStatus")};
                fields[Property_WorkOrderSubStepID] = {type: 0, data: wo.currentSubStepID};
                fields[Property_WorkOrderRunSubStepID] = {type: 0, data: wo.currentSubStepRunID};
                fields[Property_WorkOrderNewFlag] = {type: 0, data: wo.newFlag==1?1:0};

                for(var i= 0,expfarr = WOEXPF.split(",");i<expfarr.length;i++){
                    var expf = expfarr[i].trim();
                    if(!$F.isEmpty(expf)){
                        var mTmpStr = "TEMP.WORKORDER"+expf;
                        fields[mTmpStr] = {type: 0, data: wo.getFieldValue(expf)};
                    }
                }
                wo.instance.batchFireValue(fields, true);
                wo.nextStepInfo.getNextStep(wo.struct, currentStepId, wo.instance);

            };
            
            var loadWorkorder = function(workorderGuid, objective, subFlag, addinId, tabName, subId, parameters){
            	var newFlag = loadMeData(workorderGuid);
                wo.newFlag = newFlag;
                var currentStepId = wo.woBoundData.getValue("CurStep_ID");
                if(newFlag == 1){//new wo
                    wo.oldFrameId = "";
                    wo.oldStepId = "";
                }else{
                    wo.oldFrameId = wo.woBoundData.getValue("WORKORDERFRAME_ID");
                    wo.oldStepId = currentStepId;
                }
                wo.frameId = wo.woBoundData.getValue("WORKORDERFRAME_ID");
                wo.curStepId = currentStepId;

                //setCurrentWOStatus
                wo.buttonStatus.setCurrentWOStatus(wo, newFlag, subFlag);

                var ins = wo.loadDynPageInfo(workorderGuid, parameters);
                if(!$F.isNull(ins)){
                    var otId = "";
                    if(objective){
                        otId = objective.getValue("OBJECTIVETYPE_ID");
                        ins.flag = (objective.flag === 1);
                    }

                    wo.nextStepInfo.getNextStep(wo.struct, currentStepId, wo.instance);
                    if(! tabName){
                        tabName = "工单";
                    }

                    project.openDyn(tabName, wo.instance, objective);
//                    tab.data("instance", wo.instance).data("addinId",addinId.toUpperCase())
//                        .data("otId", otId)
//                        .data("subId", subId);

                    project.events.register($CONST.ModuleEvent.ECM_CUSTOMERCHANGE, wo.instance.id, function(p, ev){
                        var w = ev.w;
                        if(w.instance.flag){//只有新建工单时候，当前客户改变需要同时去修改instance.objective上的值
                            w.instance.objective.setValue("customer_guid", project.getCustomerGuid());
                            w.woBoundData.NewValueEdit("customer_guid", project.getCustomerGuid());
                        }
                    }, {w : wo});
                    ins.doCmdIncludeComponents("P-99");
                }
                return ins;
            };

            this.loadDynPageInfo = function(workorderGuid, parameters){
                var curStruct = wo.struct.getStruct();
                var curStepId = wo.getCurStepId();
                var currentNode = wo.struct.getOneNode(curStepId);
                if(!currentNode){
                    $F.log("Workorder - loadDynPageInfo", "None current node found by stepId" + curStepId);
                    return;
                }

                // Fixed by kevin, ignore addinType property, estimate case with groupIda is empty or not. 
                if (currentNode.GroupIDAMobile)
                	wo.showBuildId = currentNode.GroupIDAMobile;
                else if (currentNode.GroupIDA)
                	wo.showBuildId = currentNode.GroupIDA;
                else {
                	if (curStruct.GroupIDAMobile)
                		wo.showBuildId = curStruct.GroupIDAMobile;
                	else
                		wo.showBuildId = curStruct.GroupIDA;
                }
                	
//                if(currentNode.addinType == 0){
//                    wo.showBuildId = curStruct.GroupIDA;
//                }else if(currentNode.addinType == 1){
//                    wo.showBuildId = currentNode.GroupIDA;
//                }else{
//                    $F.log("Workorder - loadDynPageInfo","No dyn page specified for current step "+curStepId);
//                    return;
//                }

                //最后一个参数为WO，代表了是工单，这样createInstance时候就不会检查是否存在当前客户
                var instance = $D.createInstance(project, wo.showBuildId, '', '', parameters, true, "WO");
                if(instance){
                    wo.instance = instance;
                    instance.onDestroy(function(){
                        project.doUnlock("workorder-" + wo.guid);
                    });

                    var fields = {};
                    fields[Property_WOSaveStatus] = {type: 0, data: wo.buttonStatus._SaveStatus==1?1:0};
                    fields[Property_WOSendStatus] = {type: 0, data: wo.buttonStatus._SendStatus==1?1:0};
                    fields[Property_WOCloseOrReOpenStatus] = {type: 0, data: wo.buttonStatus._CloseOrOpenStatus==1?1:0};
                    fields[Property_WOEndStatus] = {type: 0, data: wo.buttonStatus._EndStatus==1?1:0};
                    fields[Property_WOReOpenStatus] = {type: 0, data: wo.buttonStatus._ReOpenStatus==1?1:0};
                    fields[Property_WOCancelStatus] = {type: 0, data: wo.buttonStatus._CancelStatus==1?1:0};
                    fields[Property_WOFailedStatus] = {type: 0, data: wo.buttonStatus._FailedStatus==1?1:0};
                    fields[Property_WOTakeOverStatus] = {type: 0, data: wo.buttonStatus._TakeOverStatus==1?1:0};
                    fields[Property_WOCDStatus] = {type: 0, data: wo.buttonStatus._CDStatus==1?1:0};
                    fields[Property_WOBackStatus] = {type: 0, data: wo.buttonStatus._BackStatus==1?1:0};
                    fields[Property_WOReplyCustomerStatus] = {type: 0, data: wo.buttonStatus._ReplyCustomerStatus==1?1:0};
                    fields[Property_WoCloseFlag] = {type: 0, data: wo.buttonStatus._CloseFlag};
                    fields[Property_WorkOrderStepComments] = {type: 0, data: wo.woBoundData.getValue("CurStepComments")};
                    fields[Property_WoCurrentHandleBy] = {type: 0, data: wo.woBoundData.getValue("HandleBy_ID")};
                    fields[Property_WoCurrentHandleGrP] = {type: 0, data: wo.woBoundData.getValue("HandleGroup_ID")};
                    fields[Property_WorkOrderFrameID] = {type: 0, data: wo.woBoundData.getValue("WorkOrderFrame_ID")};
                    fields[Property_WorkOrderWorkOrderPriority] = {type: 0, data: wo.woBoundData.getValue("Priority_ID")};
                    fields[Property_WorkOrderWorkOrderExpireDate] = {type: 0, data: wo.woBoundData.getValue("ExpiredDate")};
                    fields[Property_WorkOrderForeCastDate] = {type: 0, data: wo.woBoundData.getValue("ForecastDate")};
                    fields[Property_WorkOrderStepForeCastDate] = {type: 0, data: wo.woBoundData.getValue("StepForecastDate")};
                    fields[Property_WorkOrderStatus] = {type: 0, data: wo.woBoundData.getValue("WorkOrderStatus")};
                    fields[Property_WorkOrderStepID] = {type: 0, data: wo.woBoundData.getValue("CurStep_ID")};
                    fields[Property_WorkOrderStepStatus] = {type: 0, data: wo.woBoundData.getValue("CurStepStatus")};
                    fields[Property_WorkOrderSubStepID] = {type: 0, data: wo.currentSubStepID};
                    fields[Property_WorkOrderRunSubStepID] = {type: 0, data: wo.currentSubStepRunID};
                    fields[Property_WorkOrderNewFlag] = {type: 0, data: wo.newFlag?1:0};

                    for(var i= 0,expfarr = WOEXPF.split(",");i<expfarr.length;i++){
                        var expf = expfarr[i].trim();
                        if(!$F.isEmpty(expf)){
                            var mTmpStr = "TEMP.WORKORDER"+expf;
                           	fields[mTmpStr] = {type: 0, data: wo.getFieldValue(expf)};
                        }
                    }
                    instance.batchFireValue(fields, true);

                    $F.log("Workorder - loadDynPageInfo", "Start to register event listener to wokrorder instance.");
                    instance.propertyListener('WORKORDER_' + workorderGuid, function(pName, pValue) {
                        var mStrPropertyName = pName.toUpperCase();
                        if(!wo || !wo.buttonStatus)
                            return;
                        if (wo.buttonStatus.getCloseFlag() == 1 &&
                            mStrPropertyName!=Property_OWorkOrderCancel.toUpperCase() &&
                            mStrPropertyName!=Property_OWorkOrderCD.toUpperCase() &&
                            mStrPropertyName!=Property_WorkOrderStepComments.toUpperCase() &&
                            mStrPropertyName!=Property_ShowWorkOrderCDHistory.toUpperCase() &&
                            mStrPropertyName!=Property_ShowWorkOrderHistory.toUpperCase() &&
                            mStrPropertyName!=Property_OWorkOrderCloseOrReOpen.toUpperCase() &&
                            mStrPropertyName!=Property_OWorkOrderEnd.toUpperCase() &&
                            mStrPropertyName!=Property_OWorkOrderReOpen.toUpperCase() &&
                            mStrPropertyName!=Property_OWorkOrderTakeOver.toUpperCase()){
                            return;
                        }

                        if($F.equalsIgnoreCase(mStrPropertyName, Property_WorkOrderTabClose)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOClear Result:"+ wo.clearInfo());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_WorkOrderStepComments)){
                            wo.setCurStepComments(pValue);
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderSave)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOSave Result: " + wo.save());
                            }else if (pValue == 2){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOSave 0 Result: " + wo.save(0));
                                $F.fireValue(instance, Property_OWorkOrderSave, "0");
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderSend)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOSend Flag is 0 Result:"+ wo.send(0));
                            }else if (pValue == 2){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOSend Flag is 1 Result:"+ wo.send(1));
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderCloseOrReOpen)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOClose Result:"+ wo.close());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderEnd)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOClose Result:"+ wo.closeAndReopen());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderReOpen)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOClose Result:"+ wo.closeAndReopen());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderCancel)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOCancel Result:"+ wo.cancel());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderFailed)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOfailed Close Result:"+ wo.failedClose());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderTakeOver)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOTakeOver Close Result:"+ wo.takeOver());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderCD)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOCD Close Result:"+ wo.cdInfo());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderBack)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOBack Close Result:"+ wo.back());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_OWorkOrderReplyCustomer)){
                            if (pValue == 1){
                                $F.log("WorkOrderLib.Event_PropertyChange", "WOReplyCustomer Close Result:"+ wo.replyCustomer());
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_WorkOrderWorkOrderPriority)){
                            wo.setPriorityId(pValue);
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_WorkOrderWorkOrderExpireDate)){
                            if($F.isDate(pValue)){
                                wo.setExpiredDate($F.parseDate(pValue));
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_WorkOrderForeCastDate)){
                            if($F.isDate(pValue)){
                                wo.setForecastDate($F.parseDate(pValue));
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_WorkOrderStepForeCastDate)){
                            if($F.isDate(pValue)){
                                wo.setStepForecastDate($F.parseDate(pValue));
                            }
                        }else if($F.equalsIgnoreCase(mStrPropertyName, Property_WorkOrderFrameID)){
                            wo.changeWorkorderFrame(pValue, parameters);
                        }else{
                            if (mStrPropertyName.substr(0,14)=="TEMP.WORKORDER"){
                                wo.setExtFieldValue(mStrPropertyName.substr(14, mStrPropertyName.length-14), pValue);
                            }else if (mStrPropertyName.substr(0,12)=="TEMP.WOSTEP_"){
                                wo.setSendStepInfo(mStrPropertyName.substr(12,mStrPropertyName.length-12), pValue);
                            }
                        }
                    });
                }
                return instance;
            };


            this.getFieldValue = function(fieldName){
                return wo.woBoundData.getValue(fieldName);
            };

            this.clearInfo = function(){
                var workorderGuid = wo.guid;
                var instanceId = wo.instance.id;
                wo.buttonStatus.unLockedProcessing(workorderGuid);
                wo.struct = null;
                wo.guid = "";
                wo.frameId = "";
                wo.buttonStatus = null;
                wo.oldStepId = "";
                wo.showBuildId = "";
                project.events.remove(instanceId, $CONST.ModuleEvent.ECM_CUSTOMERCHANGE);
                project.tabClose(instanceId);
                return 1;
            };

            this.getSendStepInfo = function(){
                return wo.stepFieldInfo;
            };
            this.setSendStepInfo = function(vStepField, vValue){
                if ($F.isNull(wo.stepFieldInfo)){
                    wo.stepFieldInfo = {};
                }
                var mKey = $F.trimToEmpty(vStepField).toUpperCase();
                if (wo.stepFieldInfo.hasOwnProperty(mKey)){
                    delete wo.stepFieldInfo[mKey];
                }
                wo.stepFieldInfo[mKey] = vValue;
            };

            this.save = function(closeFlag){
                if (wo.buttonStatus.getSaveStatus() != 0){
                    $F.log("Workorder.save", "No save priority");
                    $F.alert("没有保存权限不能保存");
                    return -1;
                }
                if (wo.buttonStatus.getNewFlag() != 1){
                    if (vaildCanOperate(wo.guid) <= 0){
                        $F.log("Workorder.save", "No save priority, operation has been changed.");
                        $F.alert("没有保存权限不能保存,处理人已经改变");
                        return -1;
                    }
                }
                var mExecObj = wo.instance.doCmdIncludeComponents("P112");
                if (getFlag(mExecObj,"ExecFlag")<=0){
                    return -1;
                }
                var mNewStep,mSavemain;
                if (wo.buttonStatus.getCanProceFlag()>15){//协办处理
                    mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                        "", "", $CONST.WO.WO_SysClose, "协办:"+wo.getCurStepComments(), wo.getCurStepId(), null, wo.currentSubStepID, wo.getExpectStartTime(), wo.getCurStepIdMap(), "");
                    mSavemain = wo.woBoundData;
                    mSavemain.SubTableAdd("Step", mNewStep);
                }else{//标准处理
                    mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                        "","", $CONST.WO.WO_SysClose, wo.getCurStepComments(), wo.getCurStepId(), null, "" , wo.getExpectStartTime(), wo.getCurStepIdMap(),"");
                    wo.setCurStepStatus($CONST.WO.WO_SysOpen);
                    wo.setWorkOrderStatus($CONST.WO.WO_SysOpen);
                    mSavemain = wo.woBoundData;
                    mSavemain.SubTableAdd("Step",mNewStep);
                    if (wo.oldFrameId != "" && wo.oldFrameId != wo.frameId){
                        var mNewPath = newPath(wo.guid, wo.getCurStepId(), project.groupId,
                            $E.staff.id, wo.oldStepId, wo.frameId, wo.oldFrameId, wo.getCurStepIdMap(), wo.getCurStepIdMap());
                        mSavemain.SubTableAdd("Change",mNewPath);
                    }
                    wo.instance.objective.setValue("OBJECTIVESTATUS","OPEN");
                    wo.instance.objective.setValue("priority_id", wo.getPriorityId());
                    wo.instance.objective.setValue("expireddate", wo.getExpiredDate());
                }

                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    wo.instance.doCmdIncludeComponents("P102", mExecObj);
                    if(closeFlag !== 0){
                        wo.clearInfo();
                    } else {
                        wo.instance.xmldosRemoveAll();
                    }
                    return 1;
                }else{
                    $F.log("WoRoot.WO_Back", "Save failed, please check the server log.");
                    $F.alert("保存失败，请检查服务上错误信息");
                    return -1;
                }
            };



            this.send = function(vSendFlag){
                if (wo.buttonStatus._SendStatus != 0){
                    $F.log("WoRoot.Wo_Send", "No right for send");
                    $F.alert("没有下送权限不能下送");
                    return -1;
                }
                if(wo.buttonStatus.getNewFlag() != 1){
                    if (vaildCanOperate(wo.guid) <= 0){
                        $F.log("WoRoot.Wo_Send", "No send priority, operation has been changed.");
                        $F.alert("没有下送权限不能下送,处理人已经改变");
                        return -1;
                    }
                }

                if (wo.buttonStatus.getCanProceFlag() > 15){//协办处理
                    var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                        "","", $CONST.WO.WO_SysSubStepFinish, "协办:"+wo.getCurStepComments(), wo.getCurStepId(), null, wo.currentSubStepID, wo.getExpectStartTime(0), wo.getCurStepIdMap(), "");
                    var mSavemain = wo.woBoundData;
                    var mSubStep = new BoundData("WorkOrder2_Sub" + $E.staff.epidSql);

                    mSubStep.KeyInfoEdit("Sub_GUID");
                    mSubStep.NewValueEdit("Sub_GUID", wo.currentSubStepRunID);
                    mSubStep.NewValueEdit("SubStatus", $CONST.WO.WO_SysSubStepFinish);
                    mSavemain.SubTableAdd("Step",mNewStep);
                    mSavemain.SubTableAdd("Step1",mSubStep);

                    wo.instance.xmldosRequest("", mSavemain.getData());
                    wo.instance.save();
                    if (wo.instance.save() > 0){
                        var mExecObj = {};
                        mExecObj["NEXTSTEP"] = mNewStep;
                        mExecObj["NEXTGRP"]="SUBSTEP";
                        mExecObj["NEXTBY"]="";
                        wo.instance.doCmdIncludeComponents("P103",mExecObj);
                        wo.clearInfo();
                        return 1;
                    }else{
                        $F.log("WoRoot.WO_Back", "Save failed, please check the server log.");
                        $F.alert("保存失败，请检查服务上错误信息");
                        return -1;
                    }
                }else{
                    //校验本步骤协办工单完成情况
                    var mCurrentStep = wo.struct.getOneNode(wo.getCurStepId());
                    if ($F.isNull(mCurrentStep)){
                        $F.log("WoRoot.Wo_Send", "Current step not exist.");
                        $F.alert("当前步骤不存在，请检查配置");
                        return -1;
                    }

                    var iCount = mCurrentStep.Sub.length;
                    var mMustProce = 0;
                    for (var i=0;i<iCount;i++){
                        var mTmp = mCurrentStep.Sub[i];
                        if (mTmp.MustProcess == 1){
                            mMustProce = 1;
                            break;
                        }
                    }
                    if (mMustProce == 1){
                        if (checkSubStepFinished(mCurrentStep) < 0){
                            $F.log("WoRoot.Wo_Send", "Sub step not finished, cannot send workorder.");
                            $F.alert("协办工单任务没有完成，不能下送");
                            return -1;
                        }
                    }

                  //用户工单，two_node_map, two_link_map 用户自定义流程
                    if(wo.addinId === ADDIN_WORKORDER_USER){
                        var handleBy = "", handleGrp = "", sendNextStepMapId, vSendToStep;
                        var curStepIdMap = wo.getCurStepIdMap();
                        //select l.NodeMap_GUID_To, l.CONDITIONSFLAG, l.CONDITIONSDESC, l.CONDITIONSSTR, l.NEXTTYPE, l.NEXTCONTENT, n.WORKORDERNODE_ID_ORIGINAL
                        // from two_link_map{C1} l left join two_node_map{C1} n on l.nodemap_guid_to = n.NODEMAP_GUID
                        // where l.NodeMap_GUID_From = @{C2}S
                        var data = project.commonQuerySync("ECore.Workorder.queryTwoNodeLink", [$E.staff.epidSql, curStepIdMap]);
                        if(data && data.value[0].count > 0){
                            for(var i = 0; i < data.value[0].count; i++){
                                var toNodeMapId = data.value[0].fields[i][0];
                                var conditionsFlag = data.value[0].fields[i][1];
                                var conditionsStr = data.value[0].fields[i][3];
                                var nextType = data.value[0].fields[i][4];
                                var nextContent = data.value[0].fields[i][5];

                                if(conditionsFlag == 0){//无条件
                                    sendNextStepMapId = toNodeMapId;
                                    var handleByAndGrp = fetchHandleByAndHandleGrp(nextType, nextContent);
                                    handleBy = handleByAndGrp.handleBy;
                                    handleGrp = handleByAndGrp.handleGrp;
                                    vSendToStep = data.value[0].fields[i][6];
                                    break;
                                }else if(conditionsFlag == 1){
                                    var mExpress = replaceOtherPropertyValue(conditionsStr);
                                    $F.log("WoRoot.WO_Send", "Replace conditionsStr from " + conditionsStr + " to " + mExpress);
                                    var ret = eval(mExpress);
                                    if(ret){//满足条件
                                        sendNextStepMapId = toNodeMapId;
                                        var handleByAndGrp = fetchHandleByAndHandleGrp(nextType, nextContent);
                                        handleBy = handleByAndGrp.handleBy;
                                        handleGrp = handleByAndGrp.handleGrp;
                                        vSendToStep = data.value[0].fields[i][6];
                                        break;
                                    }
                                }
                            }
                        }

                        if(!sendNextStepMapId){
                            $F.log("WoRoot.WO_Send", "Send failed, no sendNextStepMapId found.");
                            $F.alert("下送失败，未找到下一步map_id");
                            return -1;
                        }

                        var mNextNode = wo.struct.getOneNode(vSendToStep);
                        if ($F.isNull(mNextNode)){
                            $F.alert("下送的下一步不存在:" + vSendToStep);
                            $F.log("WORoot-WOSendNextStep", "Next step for send not existed: " + vSendToStep);
                            return -1;
                        }

                        var mStepComments = wo.getCurStepComments();
                        var mCurNodeID = wo.getCurStepId();

                        var mPreStepBeginTime = wo.getExpectStartTime();
                        var mDateBegin = wo.getInstancePropertyValue(Property_WOSendNextStepBeginDate);
                        var mDateEnd = wo.getInstancePropertyValue(Property_WOSendNextEndDate);
                        if ($F.isEmpty(mDateBegin)){
                            mDateBegin = $F.getDbTime();
                            if (mNextNode.NextBeginTime > 0){
                                mDateBegin = $F.dateAddFormat(mDateBegin, "hour", mNextNode.NextBeginTime);
                            }
                        }
                        if ($F.isEmpty(mDateEnd)){
                            mDateEnd = getNextEndDate(mDateBegin, mNextNode.ExpiredPeriodTypeId, mNextNode.ExpiredPeriod);
                        }
                        var mForecastDate = getNextEndDate(mDateEnd, mNextNode.ForecastUnit, -(mNextNode.ForecastLen));

                        wo.setNewValue(vSendToStep, mDateBegin, handleGrp, handleBy, mNextNode.ExpiredGrpId, mNextNode.ExpiredById, mDateEnd, mForecastDate, sendNextStepMapId);
                        var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                            handleGrp, handleBy, $CONST.WO.WO_SysSendNextStep, mStepComments, mCurNodeID, mDateEnd, "", mPreStepBeginTime, curStepIdMap, sendNextStepMapId);
                        var mNewSendPath = newPath(wo.guid, wo.getCurStepId(), project.groupId, $E.staff.id,
                            mCurNodeID, wo.frameId, "", curStepIdMap, sendNextStepMapId);

                        var mSavemain = wo.woBoundData;
                        mSavemain.SubTableAdd("Step", mNewStep);
                        mSavemain.SubTableAdd("path", mNewSendPath);

                        wo.instance.objective.setValue("OBJECTIVESTATUS", "OPEN");
                        wo.instance.objective.setValue("priority_id", wo.getPriorityId());
                        wo.instance.objective.setValue("expireddate", wo.getExpiredDate());
                        wo.instance.xmldosRequest("", mSavemain.getData());
                        if(wo.instance.save() > 0){
                            wo.instance.doCmdIncludeComponents("P103", mExecObj);
                            wo.clearInfo();
                            return 1;
                        } else {
                            $F.log("WoRoot.WO_Send", "Send failed, please check the server log.");
                            $F.alert("下送失败，请检查服务上错误信息");
                            return -1;
                        }
                    }
                    //正常模式
                    else {
                    	var mSendToStep,mMapID,mSendSubInfo;//,mSendToGrp:String,mSendToStaff:String,mDateBegin:String,mDateEnd:String;
                        wo.nextStepInfo.getNextSteping(wo.struct, wo.getCurStepId(), wo.instance);
                        mSendToStep = wo.getInstancePropertyValue(Property_WONextStepID);
                        mMapID = wo.getInstancePropertyValue(Property_WONextStepIDMap);
                        mSendSubInfo = wo.getInstancePropertyValue(Property_WOSendNextSubStepInfo);
                        if (!$F.isEmpty(mSendToStep)){
                            if (!wo.nextStepInfo.getCanNextStep(mSendToStep)){
                                $F.alert("指定的下一步不存在不能发送");
                                $F.log("WORoot.WO_SendMe", "CanSkip:"+mCurrentStep.CanSkip+"  "+_RunData.AllNextStep.getAllCanNextStep());
                                return -1;
                            }
                        }else{
                            if (vSendFlag == 0){
                                mSendToStep = wo.nextStepInfo.getOneNextStep();
                            }
                        }
                        return sendNextStepMethod(mSendToStep, mMapID, getSubStepInfo(mSendSubInfo));
                    }
                    
                }
            };

            var sendNextStepMethod = function(vSendToStep, vSendToStepMapID, vSendSubInfo){
                var mSendToGrp, mSendToStaff, mDateBegin, mDateEnd;
                $F.log("WORoot.SendNextStepMethod", "Work Order Set Next Step:"+vSendToStep);
                var mCurrentNode = wo.struct.getOneNode(wo.getCurStepId());
                var mNextNode = wo.struct.getOneNode(vSendToStep);
                if ($F.isNull(mNextNode)){
                    $F.alert("下送的下一步不存在:"+vSendToStep);
                    $F.log("WORoot.SendNextStepMethod", "Next step " + vSendToStep + " not existed.");
                    return -1;
                }
                mSendToGrp = wo.getInstancePropertyValue(Property_WOSendNextStepGroupID);
                $F.log("WORoot.Wo_Send", "Send Next Step GroupID:" + mSendToGrp);
                if (mSendToGrp.length > 0 && mSendToGrp.length < 7){//跟据动态页面的人员处理
                    mSendToStaff = wo.getInstancePropertyValue(Property_WOSendNextStepStaffID);
                    $F.log("WORoot.Wo_Send", "Send Next Step StaffID:" + mSendToStaff);
                }else{
                    if (!$F.isEmpty(mNextNode.ReturnOldStep)){
                        if (mCurrentNode.NodeId == mNextNode.ReturnOldStep){
                            mSendToGrp = project.groupId;
                            mSendToStaff = $E.staff.id;
                            $F.log("WORoot.Wo_Send", "Send Next Step Return Group:"+mSendToGrp+" By:"+mSendToStaff);
                        }else{
                            var mObj = wo.getHandleGroupIDAndByID(wo.guid, mNextNode.ReturnOldStep, wo.frameId, mNextNode.ReturnGroupFlag);
                            if (mObj["Flag"] == 1){
                                mSendToGrp = mObj["Grp"];
                                mSendToStaff = mObj["Staff"];
                                $F.log("WORoot.Wo_Send", "Send Next Step Return1 Group:"+mSendToGrp+" By:"+mSendToStaff);
                            }else{
                                $F.alert("找不到指定步骤处理人，请检查配置");
                                $F.log("WORoot.SendNextStepMethod", "No specified step handler found, please check config.")
                                return -1;
                            }
                        }
                    }else if (vSendToStep == wo.getCurStepId() &&  wo.nextStepInfo.getSendNodeMySelf() == 1){//发送给自己
                        mSendToGrp = project.groupId;
                        mSendToStaff = $E.staff.id;
                        $F.log("WORoot.Wo_Send", "Send Next Step Self Group:"+mSendToGrp+" By:"+mSendToStaff);
                    }else if (vSendToStep == wo.getCurStepId() && wo.nextStepInfo.getSendNodeGrpSelf() == 1){ //发送给当前组
                        mSendToGrp = project.groupId;
                        mSendToStaff = "";
                        $F.log("WORoot.Wo_Send", "Send Next Step Self Group:"+mSendToGrp);
                    }else{
                        mSendToGrp = mNextNode.GrpId;
                        mSendToStaff = mNextNode.ById;
                        if ($F.isEmpty(mSendToGrp)){
                            $F.alert("下送的下一步["+mNextNode.NodeName+"]步骤中没有处理组");
                            $F.log("WORoot.SendNextStepMethod", "No handleGroup found from send next step.");
                            return -1;
                        }
                        $F.log("WORoot.Wo_Send", "Send Next Step Group:"+mSendToGrp+" By:"+mSendToStaff);
                    }
                }
                //处理下一步处理人结束
                return wo.WOSendNextStep(vSendToStep, mSendToGrp, mSendToStaff, vSendToStepMapID, vSendSubInfo);
            };


            this.WOSendNextStep = function(vSendToStep, vHandleGrp, vHandleBy, vSendNextStepMapID, vSubStepInfo){
                var mDateBegin, mDateEnd;
                $F.log("WORoot.WOSendNextStep", "WorkOrder SendTo:"+vSendToStep+" SendBy:"+vHandleBy+ " SendGrp:"+vHandleGrp);
                var mNextNode = wo.struct.getOneNode(vSendToStep);
                if ($F.isNull(mNextNode)){
                    $F.alert("下送的下一步不存在:" + vSendToStep);
                    $F.log("WORoot-WOSendNextStep", "Next step for send not existed: " + vSendToStep);
                    return -1;
                }
                if (mNextNode.CheckFlag == 1){
                    var mObj = checkNodeCalc(mNextNode);
                    if (mObj["Flag"]==1){
                        vHandleGrp = mObj["Grp"];
                        vHandleBy = mObj["By"];  //继续进入质检节点
                        $F.log("Change Step By Vaild ToStepID:"+mObj["StepID"]+" ToGrp:"+ vHandleGrp+ " ToBy:"+vHandleBy,"WoSendNextStep.WoRoot");
                        if (!$.isEmpty(mObj["StepID"])){
                            $F.log("Change Step By Vaild ToStepID:"+mObj["StepID"],"WoSendNextStep.WoRoot");
                            return wo.WOSendNextStep(mObj["StepID"],vHandleGrp,vHandleBy,"NEEDBUILD",vSubStepInfo);
                        }
                    }else{
                        wo.nextStepInfo.getNextStep(wo.struct, mNextNode.WONode_ID, wo.instance, 0);
                        $F.log("WORoot.WOSendNextStep", "WorkOrder Send To :"+vSendToStep+" is CheckNode, Jump  To Next Step:"+wo.nextStepInfo.getOneNextStep());
                        return sendNextStepMethod(_RunData.AllNextStep.OneNextStep,"NEEDBUILD",vSubStepInfo);
                    }
                }
                var mExecObj = {
                    NEXTSTEP : vSendToStep,
                    NEXTSTEPMAP : vSendNextStepMapID,
                    NEXTGRP : vHandleGrp,
                    NEXTBY : vHandleBy
                };
                wo.instance.doCmdIncludeComponents("P113", mExecObj);
                if (getFlag(mExecObj,"ExecFlag") <= 0){
                    return -1;
                }
                var mPreStepBeginTime = wo.getExpectStartTime();
                mDateBegin = wo.getInstancePropertyValue(Property_WOSendNextStepBeginDate);
                mDateEnd = wo.getInstancePropertyValue(Property_WOSendNextEndDate);
                if ($F.isEmpty(mDateBegin)){
                    mDateBegin = $F.getDbTime();
                    if (mNextNode.NextBeginTime>0){
                        mDateBegin = $F.dateAddFormat(mDateBegin, "hour", mNextNode.NextBeginTime);
                    }
                }
                if ($F.isEmpty(mDateEnd)){
                    mDateEnd = getNextEndDate(mDateBegin, mNextNode.ExpiredPeriodTypeId, mNextNode.ExpiredPeriod);
                }
                var mForecastDate = getNextEndDate(mDateEnd, mNextNode.ForecastUnit, -(mNextNode.ForecastLen));
                var mStepComments = wo.getCurStepComments();
                var mCurNodeID = wo.getCurStepId();
                var mCurNodeIDMap = wo.getCurStepIdMap();
                wo.setNewValue(vSendToStep, mDateBegin, vHandleGrp, vHandleBy, mNextNode.ExpiredGrpId, mNextNode.ExpiredById, mDateEnd, mForecastDate, vSendNextStepMapID);
                var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                    vHandleGrp, vHandleBy, $CONST.WO.WO_SysSendNextStep, mStepComments, mCurNodeID, mDateEnd, "", mPreStepBeginTime, mCurNodeIDMap, vSendNextStepMapID);
                var mNewSendPath = newPath(wo.guid, wo.getCurStepId(), project.groupId, $E.staff.id,
                    mCurNodeID, wo.frameId, "", mCurNodeIDMap, vSendNextStepMapID);
                var mSavemain = wo.woBoundData;
                mSavemain.SubTableAdd("Step",mNewStep);
                mSavemain.SubTableAdd("path",mNewSendPath);
                mSavemain.SubTableAdd("SB",sendSaveSubStep(mNextNode,mDateBegin,mCurNodeID,vSubStepInfo));//保存协助工单步骤
                if (!$F.isEmpty(wo.oldFrameId) && wo.oldFrameId != wo.frameId){
                    var mNewPath = newPath(wo.guid, mCurNodeID, project.groupId, $E.staff.id,
                        wo.oldStepId, wo.frameId, wo.oldFrameId, mCurNodeIDMap, vSendNextStepMapID);
                    mSavemain.SubTableAdd("Change", mNewPath);
                }
                wo.instance.objective.setValue("OBJECTIVESTATUS","OPEN");
                wo.instance.objective.setValue("priority_id", wo.getPriorityId());
                wo.instance.objective.setValue("expireddate", wo.getExpiredDate());

                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    wo.instance.doCmdIncludeComponents("P103", mExecObj);
                    wo.clearInfo();
                    return 1;
                }else{
                    $F.log("WoRoot.WO_Send", "Send failed, please check the server log.");
                    $F.alert("下送失败，请检查服务上错误信息");
                    return -1;
                }
            };

            var sendSaveSubStep = function(vNextNode,vBeginTime,vCurrentStep,vSubStepInfo){
                var mBound = new BoundData("WorkOrder2_Sub" + $E.staff.epidSql);
                mBound.KeyInfoEdit("WorkOrder_GUID");
                mBound.deleteFlag = 1;
                mBound.NewValueEdit("WorkOrder_GUID", wo.guid);
                var iCount = vNextNode.Sub.length;
                $F.log("SendSaveSubStep.WoRoot", "Sub step count: "+iCount);
                for (var i=0;i<iCount;i++){
                    var mTmp = vNextNode.Sub[i];
                    mBound.SubTableAdd("Sub"+i, sendSaveOneSubStep(mTmp,vNextNode.WONode_ID,vBeginTime,vCurrentStep,vSubStepInfo));
                }
                return mBound;
            };


            var sendSaveOneSubStep = function(vSub, vNodeID,vBeginTime,vCurrentStep,vSubStepInfo){
                var iCount = vSubStepInfo.length;
                var mGrp="",mBy="";
                for (var i=0;i<iCount;i++){
                    var mTmpArr = vSubStepInfo[i];
                    if ($F.equalsIgnoreCase(mTmpArr[0].trim(), vSub.Child_ID)){
                        if (mTmpArr.length>1){
                            if (mTmpArr[1] == 1){
                                $F.log("WORoot.SendSaveOneSubStep", "Sub Step ignore SubID:"+vSub.Child_ID);
                                return null;
                            }else if (mTmpArr[1] == 2){//单步多人处理
                                return saveMultiSubStep(vBeginTime,vNodeID,vCurrentStep,vSub,mTmpArr);
                            }else{
                                if (mTmpArr.length>2){
                                    mGrp= $F.trimToEmpty(mTmpArr[2]);
                                    if (mTmpArr.length>3){
                                        mBy = $F.trimToEmpty(mTmpArr[3]);
                                    }
                                    $F.log("WORoot.SendSaveOneSubStep", "Sub Step SubID:"+vSub.Child_ID+" Send To Group:"+mGrp+" By:"+mBy);
                                    return getOneSubStepBound(vBeginTime,vNodeID,vCurrentStep,vSub,mGrp,mBy);
                                }else{
                                    $F.log("WORoot.SendSaveOneSubStep", "Sub Step  SubID:"+vSub.Child_ID+" Send Next Sub Info format error,no to group");
                                    return null;
                                }
                            }
                        }else{
                            $F.log("WORoot.SendSaveOneSubStep", "Sub Step  SubID:"+vSub.Child_ID+" Send Next Sub Info format error,no run flag");
                            return null;
                        }
                    }
                }
                return getOneSubStepBound(vBeginTime,vNodeID,vCurrentStep,vSub,vSub.HandleGroup_ID,vSub.HandleBy_ID);
            };

            var saveMultiSubStep = function(vBeginTime,vNodeID,vCurrentStep,vSub,vArrayList){
                var mBound = new BoundData("WorkOrder2_SubRoot" + $E.staff.epidSql);
                mBound.NotOperateRec = 1;
                var i = 2,
                    iCount = vArrayList.length;
                $F.log("WORoot.SendSaveOneSubStep", "Sub Step  SubID:"+vSub.Child_ID+" ArrayLen:"+iCount);
                while (iCount > i){
                    var mBy="",mGrp = $F.trimToEmpty(vArrayList[i]);
                    i++;
                    if (iCount > i){
                        mBy = $F.trimToEmpty(vArrayList[i]);
                    }
                    i++;
                    $F.log("WORoot.SendSaveOneSubStep", "Sub Step SubID:"+vSub.Child_ID+" Send To Group:"+mGrp+" By:"+mBy+" Index:"+i);
                    mBound.SubTableAdd("C"+i, getOneSubStepBound(vBeginTime,vNodeID,vCurrentStep,vSub,mGrp,mBy));
                }
                return mBound;
            };

            var getOneSubStepBound = function(vBeginTime,vNodeID,vCurrentStep,vSub,vGrp,vBy){
                var mBound = new BoundData("WorkOrder2_Sub" + $E.staff.epidSql);
                mBound.KeyInfoEdit("WorkOrder_GUID");
                mBound.NotFindDupli = 1;
                mBound.NewValueEdit("WorkOrder_GUID", wo.guid);
                mBound.NewValueEdit("Sub_GUID", Guid.raw());
                var mDateEnd = getNextEndDate(vBeginTime, vSub.ExprieTimeUnit, vSub.ExprieLen);
                var mForecastDate = getNextEndDate(mDateEnd, vSub.ForceTimeUnit, -vSub.ForceLen);
                mBound.NewValueEdit("SubExpireDate", mDateEnd, $CONST.BoundType.F_Date);
                mBound.NewValueEdit("SubForceTime" ,mForecastDate, $CONST.BoundType.F_Date);
                mBound.NewValueEdit("SubStatus", "OPEN");
                mBound.NewValueEdit("WorkOrderFrame_id",  wo.frameId);
                mBound.NewValueEdit("WorkOrderNode_ID", vNodeID);
                mBound.NewValueEdit("Child_ID", vSub.Child_ID);
                if ($F.isEmpty(vSub.ReturnOld)){
                    mBound.NewValueEdit("HandleGroup_ID", vGrp);
                    mBound.NewValueEdit("HandleBy_ID", vBy);
                }else{
                    if (vCurrentStep == vSub.ReturnOld){
                        mBound.NewValueEdit("HandleGroup_ID", project.groupId);
                        mBound.NewValueEdit("HandleBy_ID", $E.staff.id);
                        $F.log("getOneSubStepBound", "Sub Step Return To Current Login Staff");
                    }else{
                        var mObj = wo.getHandleGroupIDAndByID(wo.guid,vSub.ReturnOld, wo.frameId, vSub.ReturnGrp);
                        if (mObj["Flag"] == 1){
                            mBound.NewValueEdit("HandleGroup_ID", mObj["Grp"]);
                            mBound.NewValueEdit("HandleBy_ID", mObj["Staff"]);
                            $F.log("getOneSubStepBound", "Sub Step Return To Group:"+mObj["Grp"] +" Staff:"+mObj["Staff"]);
                        }else{
                            mBound.NewValueEdit("HandleGroup_ID", project.groupId);
                            mBound.NewValueEdit("HandleBy_ID","");
                            $F.log("getOneSubStepBound", "Sub Step Return  No Find And ToGroup:" + project.groupId);
                        }
                    }
                }
                return mBound;
            };

            this.getHandleGroupIDAndByID = function(vWO_GUID, vNodeID, vFrameID, vReturnGrp){
                var mReturnObj = {
                    Flag : 0
                };
                var data = project.commonQuerySync("ECore.Workorder.Path2_1", [$E.staff.epidSql, vWO_GUID, vNodeID, vFrameID]);
                if(data && data.value[0].count > 0){
                    mReturnObj = {
                        Flag : 1,
                        Grp : data.value[0].fields[0][0],
                        Staff : data.value[0].fields[0][1]
                    };
                    if(vReturnGrp == 1){
                        mReturnObj["Staff"] = "";
                    }
                }
                return mReturnObj;
            };

            this.setNewValue = function(vStepID,vStartTime,vGrpID,vStaff,vExpGrp,vExPStaff,vStepExpriedDate,vStepForecastdate,vStepID_Map){
                _TmpStr1 = wo.getCurStepId();
                _TmpStr2 = wo.getExpectStartTime();
                _TmpStr4 = wo.getHandleGroupId();
                _TmpStr5 = wo.getHandleById();
                _TmpStr6 = wo.getExpiredHandleGroupId();
                _TmpStr7 = wo.getExpiredHandleById();
                _TmpStr8 = wo.getCurStepComments();
                _TmpStr10 = wo.getStepExpiredDate();
                _TmpStr11 = wo.getStepForecastDate();
                _TmpStr12 = wo.getCurStepIdMap();

                wo.setCurStepId(vStepID);
                wo.setExpectStartTime(vStartTime);
                wo.setHandleGroupId(vGrpID);
                wo.setHandleById(vStaff);
                wo.setExpiredHandleGroupId(vExpGrp);
                wo.setExpiredHandleById(vExPStaff);
                wo.setStepExpiredDate(vStepExpriedDate);
                wo.setStepForecastDate(vStepForecastdate);
                wo.setCurStepIdMap(vStepID_Map);

            };


            var checkNodeCalc = function(vNode){
                var mReturn = {};
                var mArray = vNode.CheckArray;
                if (mArray == null){
                    mReturn["Flag"]=0;
                    return mReturn;
                }
                var mRandValue = Math.floor(Math.random()*100);
                var iCount = mArray.length;
                for (var i=0;i<iCount;i++){
                    var mTmpOne = mArray[i];
                    if (mTmpOne.RateValue >= mRandValue){//随机数落在百分比之内
                        if (calcOneExpress(mTmpOne.FilterStr)>0){
                            mReturn["Flag"]=1;
                            mReturn["StepID"]=mTmpOne.ToStepID;
                            mReturn["Grp"]=mTmpOne.ToGroup;
                            mReturn["By"]=mTmpOne.ToBy;
                            return mReturn;
                        }
                    }
                }
                mReturn["Flag"]=0;
                return mReturn;
            };



            var calcOneExpress = function(vExpress){
                var mExpress = replaceOtherPropertyValue(vExpress);
                try{
                    var mReturn = eval(mExpress);
                    $F.log("WORoot.CalcOneExpress", "Node Filter:"+vExpress+ " ReplaceValue:"+mExpress+" Return:"+mReturn);
                    if ($F.isNull(mReturn)){
                        return -1;
                    }else if (mReturn==1){
                        return 1;
                    }else if ($F.equalsIgnoreCase(mReturn, "TRUE")){
                        return 1;
                    }
                }catch(e){
                    $F.alert("条件公式运行错误:"+vExpress);
                    $F.log("WoRoot.CalcOneExpress", "eval "+vExpress+" error: "+ e.message);
                }
                return -1;
            };


            this.close = function(){
                if (wo.buttonStatus.getCloseOrOpenStatus() != 0){
                    $F.alert("没有关闭权限不能关闭");
                    $F.log("Workorder.close", "No right for close.");
                    return -1;
                }
                $F.log("Workorder.close", "In Wo_CloseMe Function");
                if (wo.buttonStatus.getCloseFlag() == 0){//非关闭工单
                    $F.log("Workorder.close", "In Wo_CloseMe Function Close WO");
                    return closeWorkorder();
                }else{//已关闭工单
                    $F.log("Workorder.close", "In Wo_CloseMe Function OPEN WO");
                    return reOpenWorkOrder();
                }
            };

            this.closeAndReopen = function(){
                $F.log("Workorder.close", "In Wo_CloseMe Function");
                if (wo.buttonStatus.getCloseFlag() == 0){//非关闭工单
                	if (wo.buttonStatus.getEndStatus() != 0){
                        $F.alert("没有关闭权限不能关闭");
                        $F.log("Workorder.close", "No right for close.");
                        return -1;
                    }
                    $F.log("Workorder.close", "In Wo_CloseMe Function Close WO");
                    return closeWorkorder();
                }else{//已关闭工单
                    if (wo.buttonStatus.getReOpenStatus() != 0){
                        $F.alert("没有关闭权限不能重新打开");
                        $F.log("Workorder.close", "No right for reopen.");
                        return -1;
                    }
                    $F.log("Workorder.close", "In Wo_CloseMe Function OPEN WO");
                    return reOpenWorkOrder();
                }
            };

            var closeWorkorder = function(){
                if (wo.buttonStatus.getNewFlag() != 1){
                    if (vaildCanOperate(wo.guid) < 0){
                        $F.alert("没有关闭权限不能关闭,当前处理人已经改变");
                        $F.log("WoRoot.closeWorkorder", "No right for close, current handler has changed");
                        return -1;
                    }
                }

                var mCurrentStep = wo.struct.getOneNode(wo.getCurStepId());
                if (mCurrentStep == null){
                    $F.alert("当前步骤不存在，请检查配置");
                    $F.log("WoRoot.closeWorkorder", "No current step found, please check the config.");
                    return -1;
                }
                var iCount = mCurrentStep.Sub.length;
                var mMustProce = 0;
                for (var i=0;i<iCount;i++){
                    var mTmp = mCurrentStep.Sub[i];
                    if (mTmp.MustProcess == 1){
                        mMustProce = 1;
                        break;
                    }
                }
                if (mMustProce == 1){
                    if (checkSubStepFinished(mCurrentStep) < 0){
                        $F.alert("协办工单任务没有完成，不能结案");
                        return -1;
                    }
                }

                var mExecObj = wo.instance.doCmdIncludeComponents("P114");
                if (getFlag(mExecObj, "ExecFlag") <= 0){
                    return -1;
                }
                var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                    "", "", $CONST.WO.WO_SysEnd, wo.getCurStepComments(), wo.getCurStepId(), null, "", wo.getExpectStartTime(), wo.getCurStepIdMap(), "");
                wo.setCurStepStatus($CONST.WO.WO_SysEnd);
                wo.setWorkOrderStatus($CONST.WO.WO_SysClose);
                var mSavemain = wo.woBoundData;
                mSavemain.SubTableAdd("Step",mNewStep);
                if (!$F.isEmpty(wo.oldFrameId) && wo.oldFrameId != wo.frameId){
                    var mNewPath = newPath(wo.guid, wo.getCurStepId(), project.groupId, $E.staff.id,
                        wo.oldStepId, wo.frameId, wo.oldFrameId, wo.getCurStepIdMap(), wo.getCurStepIdMap());
                    mSavemain.SubTableAdd("Change",mNewPath);
                }

                wo.instance.objective.setValue("OBJECTIVESTATUS","CLOSE");
                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    var struct = wo.struct.getStruct();
                    if (struct.CanGenerateOB == 1){ //插入回访记录
                        if (wo.customer_guid != "1"){
                            var iRateNum = Math.floor(Math.random() * 100) + 1;//MyFunction.getRndNum(100);
                            if (iRateNum <= struct.GenerateRate){
                                insertReplyCustomer(struct.GroupIDA2, wo.customer_guid, wo.guid);
                            }
                        }
                    }
                    wo.instance.doCmdIncludeComponents("P104", mExecObj);
                    wo.clearInfo();
                    return 1;
                }else{
                    $F.log("WoRoot.WO_Close", "Close failed, please check the server log.");
                    $F.alert("关闭失败，请检查服务上错误信息");
                    return -1;
                }
            };

            var insertReplyCustomer = function(vObjTypeID,vCustID,vWOGUID){
                var mObjType = getOneObjectiveInfo(vObjTypeID);
                if (mObjType["Flag"] == 1){
                    var data = project.commonQuerySync("ECore.Workorder.ObjCount", [vObjTypeID, vCustID, $E.staff.epidSql]);
                    if(data && data.value[0].count <= 0) {
                        var mBDStr = $F.getDbTime();
                        var mEDStr = getNextEndDate(mBDStr, mObjType["TypeID"], mObjType["Period"]);
                        insertOBRecord(Guid.raw(), vObjTypeID, mObjType["StaffID"], mObjType["GrpID"], mObjType["PriorityID"],
                            mEDStr, vCustID, $CONST.WO.WO_SysOpen, 3, 0, vWOGUID);
                    }
                }
            };
            var insertOBRecord = function(vObjID,vObjTypeID,vHandleByID,vHandleGroupID,vPriorityID,vExpriedDate,vCust_ID,vObjStatus,vTryTime,vSuccContactTime,vOldObjID){
                var result = project.commonUpdateSync("ECore.Workorder.saveObj", [vObjID, vObjID, vObjTypeID, vHandleByID, vHandleGroupID, vPriorityID, vExpriedDate, vCust_ID, vObjStatus, vTryTime, vSuccContactTime, $E.staff.epidSql])
                var result2 = project.commonUpdateSync("ECore.Workorder.saveOBList", [Guid.raw(), vObjID, vObjTypeID, "", vExpriedDate, vHandleByID, vHandleGroupID, $E.staff.epidSql]);
                if (result > 0 && result2 >0){
                    return 1;
                }else{
                    return -1;
                }
            };

            var getOneObjectiveInfo = function(vObjectTypeID){
                var mReturnObj = {};
                var data = project.commonQuerySync("ECore.Workorder.OBJTypeInfo", [vObjectTypeID]);
                if(data && data.value[0].count > 0) {
                    mReturnObj["Flag"] = 1;
                    mReturnObj["PriorityID"] = data.value[0].fields[0][0];
                    mReturnObj["Status"] = data.value[0].fields[0][1];
                    mReturnObj["GrpID"] = data.value[0].fields[0][2];
                    mReturnObj["StaffID"] = data.value[0].fields[0][3];
                    mReturnObj["Period"] = data.value[0].fields[0][4];
                    mReturnObj["TypeID"] = data.value[0].fields[0][5];
                }else{
                    mReturnObj["Flag"] = 0;
                }
                return mReturnObj;
            };

            var reOpenWorkOrder = function(){
                var mExecObj = wo.instance.doCmdIncludeComponents("P114");
                if (getFlag(mExecObj,"ExecFlag") <= 0){
                    $F.log("WoRoot.Wo_CloseMe", "In Wo_CloseMe Function OPEN Failed");
                    return -1;
                }
                var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                    "", "", $CONST.WO.WO_SysReOpen, wo.getCurStepComments(), wo.getCurStepId(), null, "", wo.getExpectStartTime(0), wo.getCurStepIdMap(), "");
                wo.setCurStepStatus($CONST.WO.WO_SysOpen);
                wo.setWorkOrderStatus($CONST.WO.WO_SysOpen);
                wo.setHandleById($E.staff.id);
                wo.setHandleGroupId(project.groupId);
                var mSavemain = wo.woBoundData;
                mSavemain.SubTableAdd("Step",mNewStep);

                wo.instance.objective.setValue("OBJECTIVESTATUS","OPEN");
                wo.instance.objective.setValue("priority_id", wo.getPriorityId());
                wo.instance.objective.setValue("expireddate", wo.getExpiredDate());
                
                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    wo.instance.doCmdIncludeComponents("P104", mExecObj);
                    loadWorkorderData(wo.guid, 0);
                    return 1;
                }else{
                    $F.log("WoRoot.WO_Close", "In Wo_CloseMe Function  OPEN Failed Do Sql Failed");
                    $F.alert("关闭失败，请检查服务上错误信息");
                    return -1;
                }
            };


            this.cancel = function(){
                var mExecObj = wo.instance.doCmdIncludeComponents("P106");
                if (getFlag(mExecObj,"ExecFlag")<=0){
                    return -1;
                }
                wo.clearInfo();
                return 1;
            };

            this.failedClose = function () {
                if (wo.buttonStatus.getFailedStatus() != 0){
                    return -1;
                }
                if (wo.buttonStatus.getNewFlag() != 1){
                    if (vaildCanOperate(wo.guid) < 0){
                        return -1;
                    }
                }
                var mCurrentStep = wo.struct.getOneNode(wo.getCurStepId());
                if (mCurrentStep==null){
                    $F.alert("当前步骤不存在，请检查配置");
                    $F.log("WoRoot.closeWorkorder", "No current step found, please check the config.");
                    return -1;
                }
                var iCount = mCurrentStep.Sub.length;
                var mMustProce = 0;
                for (var i=0;i<iCount;i++){
                    var mTmp = mCurrentStep.Sub[i];
                    if (mTmp.MustProcess == 1){
                        mMustProce = 1;
                        break;
                    }
                }
                if (mMustProce == 1){
                    if (checkSubStepFinished(mCurrentStep) < 0){
                        $F.alert("协办工单任务没有完成，不能失败结案");
                        return -1;
                    }
                }
                var mExecObj = wo.instance.doCmdIncludeComponents("P118");
                if (getFlag(mExecObj,"ExecFlag") <= 0){
                    return -1;
                }
                var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                    "", "", $CONST.WO.WO_SysFailed, wo.getCurStepComments(), wo.getCurStepId(), null, "", wo.getExpectStartTime(), wo.getCurStepIdMap(), "");
                if (!$F.isEmpty(wo.oldFrameId)){
                    wo.frameId = wo.oldFrameId;
                }

                wo.setCurStepStatus($CONST.WO.WO_SysEnd);
                wo.setWorkOrderStatus($CONST.WO.WO_SysFailed);

                var mSavemain = wo.woBoundData;
                mSavemain.SubTableAdd("Step",mNewStep);
                wo.instance.objective.setValue("OBJECTIVESTATUS","CLOSE");
                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    wo.instance.doCmdIncludeComponents("P108", mExecObj);
                    wo.clearInfo();
                    return 1;
                }else{
                    wo.setCurStepStatus($CONST.WO.WO_SysOpen);
                    wo.setWorkOrderStatus($CONST.WO.WO_SysOpen);
                    $F.log("WoRoot.WO_FailedClose", "FailedClose failed, please check the server log.");
                    $F.alert("失败关闭失败，请检查服务上错误信息");
                    return -1;
                }
            };

            this.takeOver = function(){
                if (wo.buttonStatus.getTakeOverStatus() != 0){
                    $F.alert("没有接管权限不能接管");
                    $F.log("WoRoot.WO_TakeOver", "No right for takeover");
                    return -1;
                }
                var lockRet = project.doLock("workorder-" + wo.guid);
                if (!lockRet){
                    $F.alert("没有加锁成功，不能接管,此工单正由其它人处理中");
                    $F.log("WoRoot.WO_TakeOver", "Lock failed, cannot takeover when other is operating.");
                    return -1;
                }
                var mExecObj = wo.instance.doCmdIncludeComponents("P115");
                if (getFlag(mExecObj,"ExecFlag") <= 0){
                    project.doUnlock("workorder-" + wo.guid);
                    return -1;
                }
                var mNewStep = newStep(wo.guid, wo.getHandleGroupId(), wo.getHandleById(),
                    	project.groupId, $E.staff.id, wo.buttonStatus.getCloseFlag()==0?$CONST.WO.WO_SysTick:$CONST.WO.WO_SysTickClose, 
                    	wo.getCurStepComments(), wo.getCurStepId(), null, "", wo.getExpectStartTime(), wo.getCurStepIdMap(), "");
                if (!$F.isEmpty(wo.oldFrameId)){
                    wo.frameId = wo.oldFrameId;
                }
                wo.setCurStepStatus($CONST.WO.WO_SysOpen);
                wo.setWorkOrderStatus($CONST.WO.WO_SysOpen);
                wo.setHandleGroupId(project.groupId);
                wo.setHandleById($E.staff.id);
                var mSavemain = wo.woBoundData;
                mSavemain.SubTableAdd("Step",mNewStep);

                wo.instance.objective.setValue("OBJECTIVESTATUS","OPEN");
                wo.instance.objective.setValue("priority_id", wo.getPriorityId());
                wo.instance.objective.setValue("expireddate", wo.getExpiredDate());
                
                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    wo.instance.doCmdIncludeComponents("P105", mExecObj);
                    loadWorkorderData(wo.guid, 0);
                    return 1;
                }else{
                    project.doUnlock("workorder-" + wo.guid);
                    $F.log("WoRoot.WO_FailedClose", "FailedClose failed, please check the server log.");
                    return -1;
                }
            };

            this.cdInfo = function(){
                if (wo.buttonStatus.getCDStatus() != 0){
                    $F.alert("没有催单权限不能催单");
                    $F.log("WoRoot.WO_CDInfo", "No right for cdInfo");
                    return -1;
                }
                var mExecObj = wo.instance.doCmdIncludeComponents("P111");
                if (getFlag(mExecObj,"ExecFlag") <= 0){
                    return -1;
                }

                var mStepComments = wo.getCurStepComments();
                if ($F.isEmpty(mStepComments)){
                    $F.alert("请输入催单信息");
                    return -1;
                }
                var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                    wo.getHandleGroupId(), wo.getHandleById(), $CONST.WO.WO_SysURGE, mStepComments, wo.getCurStepId(), null, wo.currentSubStepID, wo.getExpectStartTime(), wo.getCurStepIdMap(), "");

                var mRs = $F.ajaxSync("SystemDo5",{
                    token : project.token,
                    dbPool : "",
                    xml : mNewStep.getData()
                }, project.digest);
                if (mRs){
                    wo.instance.doCmdIncludeComponents("P101", mExecObj);
                    wo.clearInfo();
                    return 1
                }else{
                    $F.alert("保存失败，请检查服务上错误信息");
                    $F.log("WoRoot.Wo_CDInfo", "Save cdInfo failed");
                    return -1;
                }
            };

            this.back = function () {
                if (wo.buttonStatus.getBackStatus() != 0){
                    $F.alert("没有退单权限不能退单");
                    $F.log("WoRoot.Wo_Back", "No right for back.");
                    return -1;
                }
                if (vaildCanOperate(wo.guid) < 0){
                    $F.alert("没有退单权限不能退单,当前处理人已经改变");
                    $F.log("WoRoot.Wo_Back", "No right for back, current handler has changed");
                    return -1;
                }
                if (wo.oldFrameId != wo.frameId || wo.oldStepId != wo.getCurStepId()){
                    $F.alert("已经更改过当前工单，不能退单");
                    $F.log("WORoot.WO_Back", "Current workorder has changed, cannot back.");
                    return -1;
                }
                var mExecObj = wo.instance.doCmdIncludeComponents("P117");
                if (getFlag(mExecObj,"ExecFlag") <= 0){
                    return -1;
                }
                var mBackToGrp,mBackToBy,mBackStepID,mBackFrameID,mBackPathID,mBackStepIDMap;
                mBackToGrp = wo.getInstancePropertyValue(Property_WOBackGrpID);
                if (mBackToGrp && mBackToGrp.length > 0 && mBackToGrp.length < 7){//跟据动态页面的人员处理
                    mBackToBy = wo.getInstancePropertyValue(Property_WOBackStaffID);
                }else{
                    mBackToGrp = "";
                    mBackToBy = "";
                }
                var mReturnStep = getBackStepObj(wo.guid);
                if (mReturnStep["Flag"]!=1){
                    $F.alert("退单失败,不能获取退单步骤");
                    $F.log("WORoot.WO_Back", "Back failed, cannot found the back step.");
                    return -1;
                }
                mBackStepID = mReturnStep["StepID"];
                mBackFrameID = mReturnStep["FrameID"];
                mBackPathID = mReturnStep["PathID"];
                mBackStepIDMap = mReturnStep["StepIDMap"];
                var mCurrentStep = wo.getCurStepId();
                var mCurrentNode = wo.struct.getOneNode(wo.getCurStepId());
                var mBackStepNode = wo.struct.getOneNode(mBackStepID);
                if ($F.isNull(mBackStepNode)){
                    $F.alert("退单失败,不能获取退单步骤-步骤已经不存在");
                    $F.log("WORoot.WO_Back", "Back failed, back step is not existed.");
                    return -1;
                }
                if ($F.isEmpty(mBackToGrp)){
                    if (mCurrentNode.CanBackToBy == 1){
                        mBackToGrp = mReturnStep["GrpID"];
                        mBackToBy = mReturnStep["StaffID"];
                    }else if(!$F.isEmpty(mBackStepNode.ReturnOldStep)){
                        var mObj = wo.getHandleGroupIDAndByID(wo.guid,mBackStepNode.ReturnOldStep, wo.frameId, mBackStepNode.ReturnGroupFlag);
                        if (mObj["Flag"]== 1){
                            mBackToGrp = mObj["Grp"];
                            if (mCurrentNode.ReturnGroupFlag == 1){
                                mBackToBy = "";
                            }else{
                                mBackToBy = mObj["Staff"];
                            }
                        }else{
                            $F.alert("找不到指定步骤处理人，请检查配置");
                            $F.log("WORoot.WO_Back", "Cannot find current handler, please check the config.");
                            return -1;
                        }
                    }else{
                        mBackToGrp = mBackStepNode.GrpId;
                        mBackToBy = mBackStepNode.ById;
                    }
                }
                var mPreBeginTime = wo.getExpectStartTime();
                var mDateBegin = $F.getDbTime();
                var mDateEnd = getNextEndDate(mDateBegin, mBackStepNode.ExpiredPeriodType_ID, mBackStepNode.ExpiredPeriod);
                var mForecastDate = getNextEndDate(mDateEnd, mBackStepNode.ForecastUnit, -(mBackStepNode.ForecastLen));
                var mBackString = wo.getCurStepComments() + "       从步骤["+mCurrentNode.NodeName+"]处理组["+
                    project.groupName+"]处理人[" +
                    $E.staff.name+"]     退回到步骤["+
                    mBackStepNode.NodeName+"]处理组["+ project.getRolegroupDescById(mBackToGrp)+"]处理人[" +
                    project.getStaffNameById(mBackToBy)+"]";
                var mBackStepMapID = wo.getCurStepIdMap();
                wo.setNewValue(mBackStepID,mDateBegin,mBackToGrp,mBackToBy,mBackStepNode.ExpiredGrpId,
                    mBackStepNode.ExpiredById,mDateEnd,mForecastDate,mBackStepIDMap);
                var mHisBound = newStep(wo.guid, project.groupId, $E.staff.id,
                    mBackToGrp, mBackToBy, $CONST.WO.WO_SysBack, mBackString, mCurrentStep, mDateEnd, "", mPreBeginTime, mBackStepMapID, mBackStepIDMap);
                var mDelBound = new BoundData("workorderpath2"+$E.staff.epidSql);
                mDelBound.deleteFlag = 1;
                mDelBound.KeyInfoEdit("WorkOrderPath_GUID");
                mDelBound.NewValueEdit("WorkOrderPath_GUID",mBackPathID);

                var mSavemain = wo.woBoundData;
                mSavemain.SubTableAdd("Step",mHisBound);
                mSavemain.SubTableAdd("path",mDelBound);
                mSavemain.SubTableAdd("SB", sendSaveSubStep(mBackStepNode, mDateBegin, "", []));//保存协助工单步骤


                wo.instance.objective.setValue("OBJECTIVESTATUS","OPEN");
                wo.instance.objective.setValue("priority_id", wo.getPriorityId());
                wo.instance.objective.setValue("expireddate", wo.getExpiredDate());
                
                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    wo.instance.doCmdIncludeComponents("P107", mExecObj);
                    wo.clearInfo();
                    return 1;
                }else{
                    wo.restore();
                    $F.log("WoRoot.WO_Back", "Back failed, please check the server log.");
                    $F.alert("保存失败，请检查服务上错误信息");
                    return -1;
                }
            };

            this.restore = function(){
                wo.setCurStepId(_TmpStr1);
                wo.setExpectStartTime(_TmpStr2);
                wo.setHandleGroupId(_TmpStr4);
                wo.setHandleById(_TmpStr5);
                wo.setExpiredHandleGroupId(_TmpStr6);
                wo.setExpiredHandleById(_TmpStr7);
                wo.setCurStepComments(_TmpStr8);
                wo.setStepExpiredDate(_TmpStr10);
                wo.setStepForecastDate(_TmpStr11);
                wo.setCurStepIdMap(_TmpStr12);
            };

            this.replyCustomer = function(){
                if (wo.buttonStatus.getReplyCustomerStatus() != 0){
                    $F.alert("没有回复权限不能回复");
                    $F.log("WoRoot.Wo_Back", "No right for reply customer.");
                    return -1;
                }
                if (vaildCanOperate(wo.guid) < 0){
                    $F.alert("没有回复权限不能回复,当前处理人已经改变");
                    $F.log("WoRoot.Wo_ReplyCustomer", "No right for reply customer, current handler has changed");
                    return -1;
                }

                var mStepComments = wo.getCurStepComments();
                var mNewStep = newStep(wo.guid, project.groupId, $E.staff.id,
                    "", "", $CONST.WO.WO_SysReplyCustomer, mStepComments, wo.getCurStepId(), null, wo.currentSubStepID, wo.getExpectStartTime(), wo.getCurStepIdMap(), "");

                wo.instance.xmldosRequest("", mSavemain.getData());
                if(wo.instance.save() > 0){
                    project.openCustomerTab();
                    return 1;
                }else{
                    wo.restore();
                    $F.log("WoRoot.Wo_ReplyCustomer", "Reply customer failed, please check the server log.");
                    $F.alert("保存失败，请检查服务上错误信息");
                    return -1;
                }
            };

            var getBackStepObj = function(workorderGuid){
                var mReturnObj = {};
                var data = project.commonQuerySync("ECore.Workorder.Path2", [$E.staff.epidSql, workorderGuid]);
                if(data && data.value[0].count > 0) {
                    mReturnObj["Flag"] = 1;
                    mReturnObj["PathID"] = data.value[0].fields[0][0];
                    mReturnObj["StepID"] = data.value[0].fields[0][1];
                    mReturnObj["GrpID"] = data.value[0].fields[0][2];
                    mReturnObj["StaffID"] = data.value[0].fields[0][3];
                    mReturnObj["FrameID"] = data.value[0].fields[0][4];
                    mReturnObj["StepIDMap"] = data.value[0].fields[0][5];
                }else{
                    mReturnObj["Flag"] = 0;
                }
                return mReturnObj;
            };

            this.changeWorkorderFrame = function(vFrameID, parameters){
                if ($F.isEmpty(vFrameID) || vFrameID == wo.frameId){
                    return ;
                }
                var mTmpStruct = fetchStruct(project, vFrameID);
                if ($F.isNull(mTmpStruct)){
                    return ;
                }
                wo.frameId = vFrameID;
                wo.setFrameStruct(mTmpStruct, parameters);
            };

            this.setFrameStruct = function(struct, parameters){
                wo.struct = struct;
                wo.setCurStepId(wo.struct.getFirstNode());
                wo.loadDynPageInfo(wo.guid, parameters);
                wo.nextStepInfo.getNextStep(wo.struct, wo.getCurStepId(), wo.instance);
            };

            this.setExtFieldValue = function(vFieldName, vValue){
                vFieldName = vFieldName.trim().toUpperCase();
                if (wo.allExtFields.hasOwnProperty(vFieldName)){
                    wo.woBoundData.NewValueEdit(vFieldName, vValue);
                }
            };

            this.getInstancePropertyValue = function(propertyName){
                return this.instance.getValue(propertyName, this.instance.runtime) || '';
            };


            var replaceOtherPropertyValue = function(vRelStr){
                var iB = vRelStr.indexOf("[");
                var iE,mProName,mAllRel={};
                while (iB>=0){
                    iE=vRelStr.indexOf("]",iB);
                    if (iE>iB){
                        mProName = vRelStr.substr(iB+1,iE-iB);//不要[ ]
                        mAllRel[mProName.trim().toUpperCase()] = mProName.trim().toUpperCase();
                        iB = vRelStr.indexOf("[",iE);
                    }else{
                        break;
                    }
                }
                for(var key in mAllRel){
                    vRelStr = $F.replaceIngoreCase(vRelStr, mAllRel[key], wo.getInstancePropertyValue(mAllRel[key]));
                }
                return vRelStr;
            };

            var getSubStepInfo = function(vSubStepInfo){
                if ($F.isEmpty(vSubStepInfo)){
                    return [];
                }
                var mTmp = vSubStepInfo.split("|");
                $F.log("WORoot.getSubStepInfo", "Sub Step Info:"+vSubStepInfo);
                //步骤ID，0/1(1表示这个协办步骤忽略),处理组，处理人|步骤ID，0/1(1表示这个协办步骤忽略),处理组，处理人|步骤ID，0/1(1表示这个协办步骤忽略),处理组，处理人.....
                var i,iCount = mTmp.length;
                var mResultArr = [];
                for (i=0;i<iCount;i++){
                    mResultArr[i] = mTmp[i].split(",");
                }
                return mResultArr;
            };

            var vaildCanOperate = function(workorderGuid){
                return project.doLockCheck("workorder-" + workorderGuid);
            };

            var getFlag = function(vObj,vFlagKey){
            	if(!vObj){
            		return 1;
            	}
                var mFlag = vObj[vFlagKey.toUpperCase()];
                if (mFlag == null){
                    return 1;
                }else if (typeof(mFlag) == "string") {
                    return parseInt(mFlag);
                }else{
                    return -1;
                }
            };

            var checkSubStepFinished = function(currentStep){
                var data = project.commonQuerySync("ECore.Workorder.WOSub", [$E.staff.epidSql, wo.guid]);
                if(data && data.value[0].count > 0) {
                    var subMap = {};
                    for(var i=0;i<data.value[0].count;i++){
                        var fields = data.value[0].fields[i];
                        subMap[fields[0]] = fields[1].toUpperCase();
                    }
                    var allNodes = wo.struct.getAllNodes();
                    for(var i=0;i<allNodes.length;i++){
                        var node = allNodes[i];
                        if (node.MustProcess == 1){
                            if(!$F.isNull(subMap[node.Child_ID]) && subMap[node.Child_ID] != "FINISH"){
                                return -1;
                            }
                        }
                    }
                }else{
                    return 1;
                }
            };

            var newStep = function(vWorderGUID, vOldGrpID, vOldByid, vHandleGrpID, vHandleByID, vWOStatus, vComments, vStepIDA, vStepExpired, vChildID, vStartTime, vFromMapID, vToMapID){
                var stepBoundData = new BoundData("workorderstep2" + $E.staff.epidSql);
                stepBoundData.notFindDupli = 1;
                stepBoundData.KeyInfoEdit("WORKORDER_GUID");
                stepBoundData.NewValueEdit("WORKORDER_GUID",vWorderGUID);
                stepBoundData.NewValueEdit("WORKORDERSTEP_GUID",Guid.raw());
                stepBoundData.NewValueEdit("OldHANDLEBY_ID",vOldByid);
                stepBoundData.NewValueEdit("OldHANDLEGROUP_ID",vOldGrpID);
                stepBoundData.NewValueEdit("HANDLEBY_ID",vHandleByID);
                stepBoundData.NewValueEdit("HANDLEGROUP_ID",vHandleGrpID);
                stepBoundData.NewValueEdit("WORKORDERSTEPSTATUS",vWOStatus);
                stepBoundData.NewValueEdit("COMMENTS",vComments);
                stepBoundData.NewValueEdit("MODIFIEDdate", $F.getDbTime() ,$CONST.BoundType.F_Date);
                stepBoundData.NewValueEdit("WORKORDERSTEPID",vStepIDA);
                stepBoundData.NewValueEdit("From_StepIDMap",vFromMapID);
                stepBoundData.NewValueEdit("To_StepIDMap",vToMapID);
                if (!$F.isEmpty(vStepExpired)){
                    stepBoundData.NewValueEdit("StepExpired", vStepExpired, $CONST.BoundType.F_Date);
                }
                if (!$F.isEmpty(vStartTime)){
                    stepBoundData.NewValueEdit("StepStart", vStartTime, $CONST.BoundType.F_Date);
                }
                stepBoundData.NewValueEdit("Child_ID",vChildID);
                var sendStepInfo = wo.getSendStepInfo();
                if (!$F.isNull(sendStepInfo)){
                    for (var mField in sendStepInfo){
                        $F.log("WORoot.NewStep", "Step Field:"+mField+" Value:"+sendStepInfo[mField]);
                        stepBoundData.NewValueEdit(mField, sendStepInfo[mField]);
                    }
                }
                return stepBoundData;
            };

            var newPath = function(vWorkOrderGUID, vToStepID, vHandleGrpID, vHandleByID, vFromStepID, vWOFrame_ID, vChangeWorkOrderFrom, vFromMapID, vToMapID){
                var pathBoundData = new BoundData("workorderpath2" + $E.staff.epidSql);
                pathBoundData.notFindDupli = 1;
                pathBoundData.KeyInfoEdit("WORKORDER_GUID");
                pathBoundData.NewValueEdit("WORKORDER_GUID",vWorkOrderGUID);
                pathBoundData.NewValueEdit("ToStepID",vToStepID);
                pathBoundData.NewValueEdit("HANDLEGROUP",vHandleGrpID);
                pathBoundData.NewValueEdit("HANDLEBY",vHandleByID);
                pathBoundData.NewValueEdit("MODIFIEDdate", $F.getDbTime(), $CONST.BoundType.F_Date);
                pathBoundData.NewValueEdit("FromStepID",vFromStepID);
                pathBoundData.NewValueEdit("WorkOrderPath_Guid", Guid.raw());
                pathBoundData.NewValueEdit("WOFrame_ID",vWOFrame_ID);
                pathBoundData.NewValueEdit("FromFrameID",vChangeWorkOrderFrom);
                pathBoundData.NewValueEdit("From_StepIDMap",vFromMapID);
                pathBoundData.NewValueEdit("To_StepIDMap",vToMapID);
                return pathBoundData;
            };

            var getNextEndDate = function(date, c, v){
                return $F.getNextEndDate(date, c, v, project.getCache($CONST.CacheName.FREE_DATE));
            }
        };


        return {
            create : function(proj){
                return new Workorder(proj);
            },
            fetchWOStruct : function(proj, woId){
                return fetchStruct(proj, woId);
            }
        };

    });